Well, since it not a submission per say. Here is the sample source code that
John wanted me to so you all.
Enjoy! Comments welcome!!
...
Laters!
D Glenn
------------------------
David Glenn
---------------
D Glenn 3D Computer Graphics & Media Systems.
www.dglenn.com
------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=46681#46681
// Suggested Revisions to osgText::Text class.
// John Markano 3/21/2012
//
// The code below includes suggested fixes for two problems in osgText::Text
// in the OpenSceneGraph 2.8.1 release:
// (1) Text in object coordinates may be rendered with the wrong size.
// If an application requests a font resolution that the font doesn't
// support, OpenSceneGraph uses the closest supported
// resolution. osgText::Text does not handle this situation properly.
// It uses the requested resolution in some calculations where the
// actual resolution is more appropriate.
// (2) Text in screen coordinates may not be scaled properly when a
// perspective projection is specified. In particular, the displayed text
// size may vary with the field of view when it should remain constant
// relative to the screen.
//
// A class TextImproved is defined below to correct these problems. This class
// inherits osgText::Text and replaces three virtual functions in the parent
// class:
// - computeLastCharacterOnLine (for the first issue above)
// - computeGlyphRepresentation (for the first issue above)
// - computePositions (for the second issue above)
//
// Each of these functions includes suggested changes to the original code.
// The original code is also left in place for comparison. The preprocessor
// variable USE_ORIGINAL_CODE can be set to a non-zero value to compile the
// original code instead of the improved code.
//
// An example program is also provided below to provide a before-and-after
// illustration of these changes. This example program splits the screen
// into four quadrants, where
// - The upper left quadrant contains black text generated by osgText::Text
// with screen coordinates specified. It changes size with the field of
// view, but its size should be fixed.
// - The upper right quadrant contains black text generated by the
// TextImproved class defined below. This text should, and does, appear
// with a constant height of around 100 pixels. (No reference scale is
// provided.)
// - The lower left quadrant contains red text generated by osgText::Text
// with object coordinates specified. It should be one unit tall, but
// its actual size varies depending on what the active font supports.
// In this example, it's less than half as tall as the requested size
// because the default font resolution of 32 is much higher than the
// supported (by DefaultFont) resolution of 12.
// - The lower right quadrant contains red text generated by the TextImproved
// class. It displays closer to the correct height of one unit.
//
// The example program allows the user to increase or decrease the field
// of view using keystrokes. Type '+' to increase the field of view, or '-'
// to decrease the field of view. The camera position is fixed, so this
// is the only available viewing parameter control.
//
// This code was developed and tested using Red Hat Enterprise Linux 5.5,
// Qt 4.5.2 and OpenSceneGraph 2.8.1.
//
// This fix uses an uppercase E to find the available font size. This is
// a kludge that is inappropriate for many fonts. A suggested
// improvement would be to add a function to osgText::Font (and the
// DefaultFont subclass) to return the supported font resolution that is
// closest to the requested resolution.
#include <osg/Camera>
#include <osg/Geode>
#include <osg/Geometry>
#include <osg/GL>
#include <osg/Group>
#include <osg/Math>
#include <osg/Matrix>
#include <osg/Notify>
#include <osg/Vec3>
#include <osg/Vec3d>
#include <osgGA/GUIEventHandler>
#include <osgText/Text>
#include <osgViewer/Viewer>
#define USE_ORIGINAL_CODE (0)
using namespace osg;
using namespace osgText;
class TextImproved : public osgText::Text
{
protected:
String::iterator computeLastCharacterOnLine(osg::Vec2& cursor, String::iterator
first,String::iterator last)
{
Font* activefont = getActiveFont();
if (!activefont) return last;
#if USE_ORIGINAL_CODE
float hr = _characterHeight/getFontHeight();
#else
// Use an upper case E to determine which font size is available
// near the requested font resolution.
// Then compute a scale factor to scale the font to the requested
// character height. Include a factor of 0.7 to allow lower
// case characters to drop below the base of capital letters.
Font::Glyph* glyphGenericUpper = activefont->getGlyph(_fontSize, 'E');
float hr = 0.7 * (glyphGenericUpper
? _characterHeight/glyphGenericUpper->t()
: _characterHeight/getFontHeight());
#endif
float wr = hr/_characterAspectRatio;
bool kerning = true;
unsigned int previous_charcode = 0;
String::iterator lastChar = first;
std::set<unsigned int> deliminatorSet;
deliminatorSet.insert(' ');
deliminatorSet.insert('\n');
deliminatorSet.insert(':');
deliminatorSet.insert('/');
deliminatorSet.insert(',');
deliminatorSet.insert(';');
deliminatorSet.insert(':');
deliminatorSet.insert('.');
for(bool outOfSpace=false;lastChar!=last;++lastChar)
{
unsigned int charcode = *lastChar;
if (charcode=='\n')
{
return lastChar;
}
Font::Glyph* glyph = activefont->getGlyph(_fontSize, charcode);
if (glyph)
{
float width = (float)(glyph->s()) * wr;
//float height = (float)(glyph->t()) * hr;
#ifdef TREES_CODE_FOR_MAKING_SPACES_EDITABLE
if (width == 0.0f) width = glyph->getHorizontalAdvance() * wr;
//if (height == 0.0f) height = glyph->getVerticalAdvance() * hr;
#endif
if (_layout==RIGHT_TO_LEFT)
{
cursor.x() -= glyph->getHorizontalAdvance() * wr;
}
// adjust cursor position w.r.t any kerning.
if (kerning && previous_charcode)
{
switch(_layout)
{
case LEFT_TO_RIGHT:
{
osg::Vec2 delta(activefont->getKerning(_fontSize,
previous_charcode,charcode,_kerningType));
cursor.x() += delta.x() * wr;
cursor.y() += delta.y() * hr;
break;
}
case RIGHT_TO_LEFT:
{
osg::Vec2 delta(activefont->getKerning(_fontSize,
charcode,previous_charcode,_kerningType));
cursor.x() -= delta.x() * wr;
cursor.y() -= delta.y() * hr;
break;
}
case VERTICAL:
break; // no kerning when vertical.
} // check to see if we are still within line if not
move to next line.
}
switch(_layout)
{
case LEFT_TO_RIGHT:
{
if (_maximumWidth>0.0f && cursor.x()+width>_maximumWidth)
outOfSpace=true;
if(_maximumHeight>0.0f && cursor.y()<-_maximumHeight)
outOfSpace=true;
break;
}
case RIGHT_TO_LEFT:
{
if (_maximumWidth>0.0f && cursor.x()<-_maximumWidth)
outOfSpace=true;
if(_maximumHeight>0.0f && cursor.y()<-_maximumHeight)
outOfSpace=true;
break;
}
case VERTICAL:
if (_maximumHeight>0.0f && cursor.y()<-_maximumHeight)
outOfSpace=true;
break;
}
// => word boundary detection & wrapping
if (outOfSpace) break;
// move the cursor onto the next character.
switch(_layout)
{
case LEFT_TO_RIGHT: cursor.x() += glyph->getHorizontalAdvance() *
wr; break;
case VERTICAL: cursor.y() -= glyph->getVerticalAdvance()
*hr; break;
case RIGHT_TO_LEFT: break; // nop.
}
previous_charcode = charcode;
}
}
// word boundary detection & wrapping
if (lastChar!=last)
{
if (deliminatorSet.count(*lastChar)==0)
{
String::iterator lastValidChar = lastChar;
while (lastValidChar!=first &&
deliminatorSet.count(*lastValidChar)==0)
{
--lastValidChar;
// Subtract off glyphs from the cursor position (to correctly
center text)
Font::Glyph* glyph = activefont->getGlyph(_fontSize,
*lastValidChar);
if (glyph)
{
switch(_layout)
{
case LEFT_TO_RIGHT: cursor.x() -=
glyph->getHorizontalAdvance() * wr; break;
case VERTICAL: cursor.y() +=
glyph->getVerticalAdvance() * hr; break;
case RIGHT_TO_LEFT: break; // nop.
}
}
}
if (first!=lastValidChar)
{
++lastValidChar;
lastChar = lastValidChar;
}
}
}
return lastChar;
}
void computeGlyphRepresentation()
{
Font* activefont = getActiveFont();
if (!activefont) return;
_textureGlyphQuadMap.clear();
_lineCount = 0;
if (_text.empty())
{
_textBB.set(0,0,0,0,0,0);//no size text
TextBase::computePositions(); //to reset the origin
return;
}
//OpenThreads::ScopedLock<Font::FontMutex>
lock(*(activefont->getSerializeFontCallsMutex()));
// initialize bounding box, it will be expanded during glyph position
calculation
_textBB.init();
osg::Vec2 startOfLine_coords(0.0f,0.0f);
osg::Vec2 cursor(startOfLine_coords);
osg::Vec2 local(0.0f,0.0f);
unsigned int previous_charcode = 0;
unsigned int linelength = 0;
bool horizontal = _layout!=VERTICAL;
bool kerning = true;
unsigned int lineNumber = 0;
#if USE_ORIGINAL_CODE
float hr = _characterHeight/getFontHeight();
#else
// Use an upper case E to determine which font size is available
// near the requested font resolution.
// Then compute a scale factor to scale the font to the requested
// character height. Include a factor of 0.7 to allow lower
// case characters to drop below the base of capital letters.
Font::Glyph* glyphGenericUpper = activefont->getGlyph(_fontSize, 'E');
float hr = 0.7 * (glyphGenericUpper
? _characterHeight/glyphGenericUpper->t()
: _characterHeight/getFontHeight());
#endif
float wr = hr/_characterAspectRatio;
for(String::iterator itr=_text.begin();
itr!=_text.end();
)
{
// record the start of the current line
String::iterator startOfLine_itr = itr;
// find the end of the current line.
osg::Vec2 endOfLine_coords(cursor);
String::iterator endOfLine_itr =
computeLastCharacterOnLine(endOfLine_coords, itr,_text.end());
linelength = endOfLine_itr - startOfLine_itr;
// Set line position to correct alignment.
switch(_layout)
{
case LEFT_TO_RIGHT:
{
switch(_alignment)
{
// nothing to be done for these
//case LEFT_TOP:
//case LEFT_CENTER:
//case LEFT_BOTTOM:
//case LEFT_BASE_LINE:
//case LEFT_BOTTOM_BASE_LINE:
// break;
case CENTER_TOP:
case CENTER_CENTER:
case CENTER_BOTTOM:
case CENTER_BASE_LINE:
case CENTER_BOTTOM_BASE_LINE:
cursor.x() = (cursor.x() - endOfLine_coords.x()) * 0.5f;
break;
case RIGHT_TOP:
case RIGHT_CENTER:
case RIGHT_BOTTOM:
case RIGHT_BASE_LINE:
case RIGHT_BOTTOM_BASE_LINE:
cursor.x() = cursor.x() - endOfLine_coords.x();
break;
default:
break;
}
break;
}
case RIGHT_TO_LEFT:
{
switch(_alignment)
{
case LEFT_TOP:
case LEFT_CENTER:
case LEFT_BOTTOM:
case LEFT_BASE_LINE:
case LEFT_BOTTOM_BASE_LINE:
cursor.x() = 2*cursor.x() - endOfLine_coords.x();
break;
case CENTER_TOP:
case CENTER_CENTER:
case CENTER_BOTTOM:
case CENTER_BASE_LINE:
case CENTER_BOTTOM_BASE_LINE:
cursor.x() = cursor.x() + (cursor.x() - endOfLine_coords.x()) *
0.5f;
break;
// nothing to be done for these
//case RIGHT_TOP:
//case RIGHT_CENTER:
//case RIGHT_BOTTOM:
//case RIGHT_BASE_LINE:
//case RIGHT_BOTTOM_BASE_LINE:
// break;
default:
break;
}
break;
}
case VERTICAL:
{
switch(_alignment)
{
// TODO: current behaviour top baselines lined up in both cases -
need to implement
// top of characters alignment - Question is this necessary?
// ... otherwise, nothing to be done for these 6 cases
//case LEFT_TOP:
//case CENTER_TOP:
//case RIGHT_TOP:
// break;
//case LEFT_BASE_LINE:
//case CENTER_BASE_LINE:
//case RIGHT_BASE_LINE:
// break;
case LEFT_CENTER:
case CENTER_CENTER:
case RIGHT_CENTER:
cursor.y() = cursor.y() + (cursor.y() - endOfLine_coords.y()) *
0.5f;
break;
case LEFT_BOTTOM_BASE_LINE:
case CENTER_BOTTOM_BASE_LINE:
case RIGHT_BOTTOM_BASE_LINE:
cursor.y() = cursor.y() - (linelength * _characterHeight);
break;
case LEFT_BOTTOM:
case CENTER_BOTTOM:
case RIGHT_BOTTOM:
cursor.y() = 2*cursor.y() - endOfLine_coords.y();
break;
default:
break;
}
break;
}
}
if (itr!=endOfLine_itr)
{
for(;itr!=endOfLine_itr;++itr)
{
unsigned int charcode = *itr;
Font::Glyph* glyph = activefont->getGlyph(_fontSize, charcode);
if (glyph)
{
float width = (float)(glyph->s()) * wr;
float height = (float)(glyph->t()) * hr;
#ifdef TREES_CODE_FOR_MAKING_SPACES_EDITABLE
if (width == 0.0f) width = glyph->getHorizontalAdvance() *
wr;
if (height == 0.0f) height = glyph->getVerticalAdvance() *
hr;
#endif
if (_layout==RIGHT_TO_LEFT)
{
cursor.x() -= glyph->getHorizontalAdvance() * wr;
}
// adjust cursor position w.r.t any kerning.
if (kerning && previous_charcode)
{
switch(_layout)
{
case LEFT_TO_RIGHT:
{
osg::Vec2 delta(activefont->getKerning(_fontSize,
previous_charcode,charcode,_kerningType));
cursor.x() += delta.x() * wr;
cursor.y() += delta.y() * hr;
break;
}
case RIGHT_TO_LEFT:
{
osg::Vec2 delta(activefont->getKerning(_fontSize,
charcode,previous_charcode,_kerningType));
cursor.x() -= delta.x() * wr;
cursor.y() -= delta.y() * hr;
break;
}
case VERTICAL:
break; // no kerning when vertical.
}
}
local = cursor;
osg::Vec2
bearing(horizontal?glyph->getHorizontalBearing():glyph->getVerticalBearing());
local.x() += bearing.x() * wr;
local.y() += bearing.y() * hr;
GlyphQuads& glyphquad =
_textureGlyphQuadMap[glyph->getTexture()];
glyphquad._glyphs.push_back(glyph);
glyphquad._lineNumbers.push_back(lineNumber);
// set up the coords of the quad
glyphquad._coords.push_back(local+osg::Vec2(0.0f,height));
glyphquad._coords.push_back(local+osg::Vec2(0.0f,0.0f));
glyphquad._coords.push_back(local+osg::Vec2(width,0.0f));
glyphquad._coords.push_back(local+osg::Vec2(width,height));
// set up the tex coords of the quad
const osg::Vec2& mintc = glyph->getMinTexCoord();
const osg::Vec2& maxtc = glyph->getMaxTexCoord();
glyphquad._texcoords.push_back(osg::Vec2(mintc.x(),maxtc.y()));
glyphquad._texcoords.push_back(osg::Vec2(mintc.x(),mintc.y()));
glyphquad._texcoords.push_back(osg::Vec2(maxtc.x(),mintc.y()));
glyphquad._texcoords.push_back(osg::Vec2(maxtc.x(),maxtc.y()));
// move the cursor onto the next character.
// also expand bounding box
switch(_layout)
{
case LEFT_TO_RIGHT:
cursor.x() += glyph->getHorizontalAdvance() * wr;
_textBB.expandBy(osg::Vec3(local.x(),local.y(),0.0f)); //lower left corner
_textBB.expandBy(osg::Vec3(cursor.x(),local.y()+height,0.0f)); //upper right
corner
break;
case VERTICAL:
cursor.y() -= glyph->getVerticalAdvance() *hr;
_textBB.expandBy(osg::Vec3(local.x(),local.y()+height,0.0f)); //upper left
corner
_textBB.expandBy(osg::Vec3(local.x()+width,cursor.y(),0.0f)); //lower right
corner
break;
case RIGHT_TO_LEFT:
_textBB.expandBy(osg::Vec3(local.x()+width,local.y(),0.0f)); //lower right
corner
_textBB.expandBy(osg::Vec3(cursor.x(),local.y()+height,0.0f)); //upper left
corner
break;
}
previous_charcode = charcode;
}
}
if (itr!=_text.end())
{
// skip over spaces and return.
while (*itr==' ') ++itr;
if (*itr=='\n') ++itr;
}
}
else
{
++itr;
}
// move to new line.
switch(_layout)
{
case LEFT_TO_RIGHT:
{
startOfLine_coords.y() -= _characterHeight * (1.0 + _lineSpacing);
cursor = startOfLine_coords;
previous_charcode = 0;
_lineCount++;
break;
}
case RIGHT_TO_LEFT:
{
startOfLine_coords.y() -= _characterHeight * (1.0 + _lineSpacing);
cursor = startOfLine_coords;
previous_charcode = 0;
_lineCount++;
break;
}
case VERTICAL:
{
startOfLine_coords.x() += _characterHeight/_characterAspectRatio *
(1.0 + _lineSpacing);
cursor = startOfLine_coords;
previous_charcode = 0;
// because _lineCount is the max vertical no. of characters....
_lineCount = (_lineCount >linelength)?_lineCount:linelength;
}
break;
}
++lineNumber;
}
TextBase::computePositions();
computeBackdropBoundingBox();
computeColorGradients();
}
virtual void computePositions(unsigned int contextID) const
{
switch(_alignment)
{
case LEFT_TOP:
_offset.set(_textBB.xMin(),_textBB.yMax(),_textBB.zMin()); break;
case LEFT_CENTER:
_offset.set(_textBB.xMin(),(_textBB.yMax()+_textBB.yMin())*0.5f,_textBB.zMin());
break;
case LEFT_BOTTOM:
_offset.set(_textBB.xMin(),_textBB.yMin(),_textBB.zMin()); break;
case CENTER_TOP:
_offset.set((_textBB.xMax()+_textBB.xMin())*0.5f,_textBB.yMax(),_textBB.zMin());
break;
case CENTER_CENTER:
_offset.set((_textBB.xMax()+_textBB.xMin())*0.5f,(_textBB.yMax()+_textBB.yMin())*0.5f,_textBB.zMin());
break;
case CENTER_BOTTOM:
_offset.set((_textBB.xMax()+_textBB.xMin())*0.5f,_textBB.yMin(),_textBB.zMin());
break;
case RIGHT_TOP:
_offset.set(_textBB.xMax(),_textBB.yMax(),_textBB.zMin()); break;
case RIGHT_CENTER:
_offset.set(_textBB.xMax(),(_textBB.yMax()+_textBB.yMin())*0.5f,_textBB.zMin());
break;
case RIGHT_BOTTOM:
_offset.set(_textBB.xMax(),_textBB.yMin(),_textBB.zMin()); break;
case LEFT_BASE_LINE: _offset.set(0.0f,0.0f,0.0f); break;
case CENTER_BASE_LINE:
_offset.set((_textBB.xMax()+_textBB.xMin())*0.5f,0.0f,0.0f); break;
case RIGHT_BASE_LINE: _offset.set(_textBB.xMax(),0.0f,0.0f); break;
case LEFT_BOTTOM_BASE_LINE:
_offset.set(0.0f,-_characterHeight*(_lineCount-1),0.0f); break;
case CENTER_BOTTOM_BASE_LINE:
_offset.set((_textBB.xMax()+_textBB.xMin())*0.5f,-_characterHeight*(_lineCount-1),0.0f);
break;
case RIGHT_BOTTOM_BASE_LINE:
_offset.set(_textBB.xMax(),-_characterHeight*(_lineCount-1),0.0f); break;
}
AutoTransformCache& atc = _autoTransformCache[contextID];
osg::Matrix& matrix = atc._matrix;
if (_characterSizeMode!=OBJECT_COORDS || _autoRotateToScreen)
{
matrix.makeTranslate(-_offset);
osg::Matrix rotate_matrix;
if (_autoRotateToScreen)
{
osg::Vec3d trans(atc._modelview.getTrans());
atc._modelview.setTrans(0.0f,0.0f,0.0f);
rotate_matrix.invert(atc._modelview);
atc._modelview.setTrans(trans);
}
matrix.postMultRotate(_rotation);
if (_characterSizeMode!=OBJECT_COORDS)
{
osg::Matrix M(rotate_matrix);
M.postMultTranslate(_position);
M.postMult(atc._modelview);
osg::Matrix& P = atc._projection;
// compute the pixel size vector.
#if USE_ORIGINAL_CODE
// pre adjust P00,P20,P23,P33 by multiplying them by the viewport
window matrix.
// here we do it in short hand with the knowledge of how the window
matrix is formed
// note P23,P33 are multiplied by an implicit 1 which would come
from the window matrix.
// Robert Osfield, June 2002.
// scaling for horizontal pixels
float P00 = P(0,0)*atc._width*0.5f;
float P20_00 = P(2,0)*atc._width*0.5f + P(2,3)*atc._width*0.5f;
osg::Vec3 scale_00(M(0,0)*P00 + M(0,2)*P20_00,
M(1,0)*P00 + M(1,2)*P20_00,
M(2,0)*P00 + M(2,2)*P20_00);
// scaling for vertical pixels
float P10 = P(1,1)*atc._height*0.5f;
float P20_10 = P(2,1)*atc._height*0.5f + P(2,3)*atc._height*0.5f;
osg::Vec3 scale_10(M(0,1)*P10 + M(0,2)*P20_10,
M(1,1)*P10 + M(1,2)*P20_10,
M(2,1)*P10 + M(2,2)*P20_10);
float P23 = P(2,3);
float P33 = P(3,3);
float pixelSizeVector_w = M(3,2)*P23 + M(3,3)*P33;
float
pixelSizeVert=(_characterHeight*sqrtf(scale_10.length2()))/(pixelSizeVector_w*0.701f);
float
pixelSizeHori=(_characterHeight/_characterAspectRatio*sqrtf(scale_00.length2()))/(pixelSizeVector_w*0.701f);
#else
// Compute the product of the projection transform and the scaling
// component of the viewport transform. Compute each term directly
// to avoid explict multiplication of zeros and ones.
float vpHalfWidth( atc._width * 0.5);
float vpHalfHeight( atc._height * 0.5);
osg::Matrix PW(
P(0,0)*vpHalfWidth, 0.0, 0.0, 0.0,
0.0, P(1,1)*vpHalfHeight, 0.0, 0.0,
P(2,0)*vpHalfWidth, P(2,1)*vpHalfHeight, P(2,2)*0.5, P(2,3),
P(3,0)*vpHalfWidth, P(3,1)*vpHalfHeight, P(3,2)*0.5, P(3,3));
float P10( PW(1,1)); // For sign check in legacy code below.
// Transform the object coordinate origin to screen coordinates.
osg::Vec4 objOriginView( M(3,0), M(3,1), M(3,2), M(3,3));
osg::Vec4 objOriginWin4( objOriginView * PW);
osg::Vec3 objOriginWin(
objOriginWin4.x()/objOriginWin4.w(),
objOriginWin4.y()/objOriginWin4.w(),
objOriginWin4.z()/objOriginWin4.w());
// Transform the object coordinate unit x (horizontal) vector from
// object coordinates to window coordinates and compute the length
// of the result.
osg::Vec4 objUnitXView(
M(0,0)+M(3,0), M(0,1)+M(3,1), M(0,2)+M(3,2), 1.0);
osg::Vec4 objUnitXWin4( objUnitXView * PW);
osg::Vec3 objUnitXWin(
objUnitXWin4.x()/objUnitXWin4.w() - objOriginWin.x(),
objUnitXWin4.y()/objUnitXWin4.w() - objOriginWin.y(),
objUnitXWin4.z()/objUnitXWin4.w() - objOriginWin.z());
float objUnitXWinLength( objUnitXWin.length());
// Transform the object coordinate unit y (vertical) vector from
// object coordinates to window coordinates. Then compute the
// length of the result.
osg::Vec4 objUnitYView(
M(1,0)+M(3,0), M(1,1)+M(3,1), M(1,2)+M(3,2), 1.0);
osg::Vec4 objUnitYWin4( objUnitYView * PW);
osg::Vec3 objUnitYWin(
objUnitYWin4.x()/objUnitYWin4.w() - objOriginWin.x(),
objUnitYWin4.y()/objUnitYWin4.w() - objOriginWin.y(),
objUnitYWin4.z()/objUnitYWin4.w() - objOriginWin.z());
float objUnitYWinLength( objUnitYWin.length());
// Compute the vertical and horizontal screen coordinate
// dimensions of a character after it is transformed into
// screen coordinates.
float pixelSizeVert( _characterHeight * objUnitYWinLength);
float pixelSizeHori(
_characterHeight / _characterAspectRatio * objUnitXWinLength);
#endif
// avoid nasty math by preventing a divide by zero
if (pixelSizeVert == 0.0f)
pixelSizeVert= 1.0f;
if (pixelSizeHori == 0.0f)
pixelSizeHori= 1.0f;
if (_characterSizeMode==SCREEN_COORDS)
{
float scale_font_vert=_characterHeight/pixelSizeVert;
float
scale_font_hori=_characterHeight/_characterAspectRatio/pixelSizeHori;
if (P10<0)
scale_font_vert=-scale_font_vert;
matrix.postMultScale(osg::Vec3f(scale_font_hori,
scale_font_vert,1.0f));
}
else if (pixelSizeVert>getFontHeight())
{
float scale_font = getFontHeight()/pixelSizeVert;
matrix.postMultScale(osg::Vec3f(scale_font, scale_font,1.0f));
}
}
if (_autoRotateToScreen)
{
matrix.postMult(rotate_matrix);
}
matrix.postMultTranslate(_position);
}
else if (!_rotation.zeroRotation())
{
matrix.makeRotate(_rotation);
matrix.preMultTranslate(-_offset);
matrix.postMultTranslate(_position);
}
else
{
matrix.makeTranslate(_position-_offset);
}
// now apply matrix to the glyphs.
for(TextureGlyphQuadMap::iterator titr=_textureGlyphQuadMap.begin();
titr!=_textureGlyphQuadMap.end();
++titr)
{
GlyphQuads& glyphquad = titr->second;
GlyphQuads::Coords2& coords2 = glyphquad._coords;
GlyphQuads::Coords3& transformedCoords =
glyphquad._transformedCoords[contextID];
unsigned int numCoords = coords2.size();
if (numCoords!=transformedCoords.size())
{
transformedCoords.resize(numCoords);
}
for(unsigned int i=0;i<numCoords;++i)
{
transformedCoords[i] =
osg::Vec3(coords2[i].x(),coords2[i].y(),0.0f)*matrix;
}
}
computeBackdropPositions(contextID);
_normal = osg::Matrix::transform3x3(osg::Vec3(0.0f,0.0f,1.0f),matrix);
_normal.normalize();
const_cast<TextImproved*>(this)->dirtyBound();
}
};
///////////////////////////////////////////////////////////////////////////////
// KeyHandler - Event handler to toggle different symbol display modes.
///////////////////////////////////////////////////////////////////////////////
class KeyHandler : public osgGA::GUIEventHandler
{
osgViewer::Viewer* _viewer;
public:
KeyHandler( osgViewer::Viewer* viewer)
: _viewer( viewer)
{}
virtual bool handle(
const osgGA::GUIEventAdapter& eventAdapter,
osgGA::GUIActionAdapter& actionAdapter)
{
switch (eventAdapter.getEventType())
{
case osgGA::GUIEventAdapter::FRAME:
_viewer->setCameraManipulator( NULL);
_viewer->getCamera()->setViewMatrixAsLookAt(
osg::Vec3d( 0.0, 0.0, 10.0), // eye
osg::Vec3d( 0.0, 0.0, 0.0), // center
osg::Vec3d( 0.0, 1.0, 0.0)); // up
break;
case osgGA::GUIEventAdapter::KEYUP:
switch (eventAdapter.getKey())
{
case '+':
case '-':
{
osg::Camera* camera( _viewer->getCamera());
double fovY, aspectRatio, zNear, zFar;
camera->getProjectionMatrixAsPerspective(
fovY, aspectRatio, zNear, zFar);
osg::notify( osg::NOTICE)
<< "PROJECTION "
<< fovY << " "
<< aspectRatio << " "
<< zNear << " "
<< zFar << std::endl;
if (eventAdapter.getKey() == '+' && fovY < 172.0)
fovY += 4.0;
if (eventAdapter.getKey() == '-' && fovY > 8.0)
fovY -= 4.0;
camera->setProjectionMatrixAsPerspective(
fovY, aspectRatio, 1.0, 1000.0);
camera->setComputeNearFarMode(
osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
}
break;
default: ;
}
break;
default: ;
}
return false;
}
};
///////////////////////////////////////////////////////////////////////////////
// main - Creates and displays text using both legacy and updated logic.
///////////////////////////////////////////////////////////////////////////////
int main( int argc, char **argv )
{
std::string textStr = "pHE,L q\npHE,L q";
// Create "unimproved text objects to the left of center.
// Black text 100 pixels tall.
osgText::Text* text100pUnimp( new osgText::Text);
text100pUnimp->setColor( osg::Vec4( 0.0, 0.0, 0.0, 1.0));
text100pUnimp->setText( textStr);
text100pUnimp->setPosition( osg::Vec3d( 0.0, 0.0, 0.0));
text100pUnimp->setCharacterSize( 100.0);
text100pUnimp->setCharacterSizeMode( osgText::Text::SCREEN_COORDS);
text100pUnimp->setAlignment( osgText::Text::RIGHT_BOTTOM);
text100pUnimp->setAutoRotateToScreen( false);
// Red text 1 object coordinate unit tall.
osgText::Text* text1uUnimp( new osgText::Text);
text1uUnimp->setColor( osg::Vec4( 1.0, 0.0, 0.0, 1.0));
text1uUnimp->setText( textStr);
text1uUnimp->setPosition( osg::Vec3d( 0.0, 0.0, 0.0));
text1uUnimp->setCharacterSize( 1.0);
text1uUnimp->setCharacterSizeMode( osgText::Text::OBJECT_COORDS);
text1uUnimp->setAlignment( osgText::Text::RIGHT_TOP);
text1uUnimp->setAutoRotateToScreen( false);
// Create "improved" text objects to the right of center.
// Black text 100 pixels tall.
TextImproved* text100pImpro( new TextImproved);
text100pImpro->setColor( osg::Vec4( 0.0, 0.0, 0.0, 1.0));
text100pImpro->setText( textStr);
text100pImpro->setPosition( osg::Vec3d( 0.0, 0.0, 0.0));
text100pImpro->setCharacterSize( 100.0);
text100pImpro->setCharacterSizeMode( osgText::Text::SCREEN_COORDS);
text100pImpro->setAlignment( osgText::Text::LEFT_BOTTOM);
text100pImpro->setAutoRotateToScreen( false);
// Red text 1 object coordinate unit tall.
TextImproved* text1uImpro( new TextImproved);
text1uImpro->setColor( osg::Vec4( 1.0, 0.0, 0.0, 1.0));
text1uImpro->setText( textStr);
text1uImpro->setPosition( osg::Vec3d( 0.0, 0.0, 0.0));
text1uImpro->setCharacterSize( 1.0);
text1uImpro->setCharacterSizeMode( osgText::Text::OBJECT_COORDS);
text1uImpro->setAlignment( osgText::Text::LEFT_TOP);
text1uImpro->setAutoRotateToScreen( false);
// Four white one-unit squares centered at the object coordinate origin.
osg::Vec3Array* vertices( new osg::Vec3Array);
vertices->push_back( osg::Vec3( -1.0, -1.0, 0.0));
vertices->push_back( osg::Vec3( 1.0, -1.0, 0.0));
vertices->push_back( osg::Vec3( -1.0, 0.0, 0.0));
vertices->push_back( osg::Vec3( 1.0, 0.0, 0.0));
vertices->push_back( osg::Vec3( -1.0, 1.0, 0.0));
vertices->push_back( osg::Vec3( 1.0, 1.0, 0.0));
vertices->push_back( osg::Vec3( -1.0, -1.0, 0.0));
vertices->push_back( osg::Vec3( -1.0, 1.0, 0.0));
vertices->push_back( osg::Vec3( 0.0, -1.0, 0.0));
vertices->push_back( osg::Vec3( 0.0, 1.0, 0.0));
vertices->push_back( osg::Vec3( 1.0, -1.0, 0.0));
vertices->push_back( osg::Vec3( 1.0, 1.0, 0.0));
osg::Vec4Array* colors( new osg::Vec4Array);
colors->push_back( osg::Vec4( 1.0, 1.0, 1.0, 1.0));
osg::Geometry* geom( new osg::Geometry);
geom->setVertexArray( vertices);
geom->setColorArray( colors);
geom->setColorBinding( osg::Geometry::BIND_OVERALL);
geom->addPrimitiveSet( new osg::DrawArrays( GL_LINES, 0, 12));
osg::Geode* geode( new osg::Geode);
geode->addDrawable( text100pUnimp);
geode->addDrawable( text1uUnimp);
geode->addDrawable( text100pImpro);
geode->addDrawable( text1uImpro);
geode->addDrawable( geom);
osgViewer::Viewer viewer;
viewer.setSceneData( geode);
viewer.addEventHandler( new KeyHandler( &viewer));
return viewer.run();
}
_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org