Commit 358baf67 authored by Isaak Lim's avatar Isaak Lim
Browse files

- cleaned up and added some documentation to TextNode

- adjusted the code in RulerPlugin and SkeletonObject accordingly

refs #269

git-svn-id: http://www.openflipper.org/svnrepo/OpenFlipper/branches/Free@14695 383ad7c9-94d9-4d36-a494-682f7c89f535
parent fd859ed6
......@@ -74,12 +74,45 @@ bool TextNode::initialised_ = false;
std::map<char, unsigned int> TextNode::charToIndex_ = TextNode::createMap();
QColor TextNode::color_ = QColor(255, 0, 0);
//----------------------------------------------------------------------------
TextNode::
TextNode( BaseNode* _parent,
std::string _name,
TextMode _textMode)
: BaseNode(_parent, _name),
size_(1),
textMode_(_textMode),
vbo_(0),
vertexBuffer_(0),
blendEnabled_(false),
texture2dEnabled_(false),
cullFaceEnabled_(false),
blendSrc_(0),
blendDest_(0)
{
updateFont();
updateVBO();
}
//----------------------------------------------------------------------------
TextNode::
~TextNode()
{
glDeleteBuffers(1, &vbo_);
}
//----------------------------------------------------------------------------
void
TextNode::
boundingBox(Vec3d& /*_bbMin*/, Vec3d& /*_bbMax*/)
......@@ -103,6 +136,49 @@ availableDrawModes() const
//----------------------------------------------------------------------------
void
TextNode::
setRenderingMode(TextMode _textMode) {
textMode_ = _textMode;
}
//----------------------------------------------------------------------------
TextNode::TextMode
TextNode::
renderingMode() {
return textMode_;
}
//----------------------------------------------------------------------------
void
TextNode::
setText(std::string _text) {
text_ = _text; updateVBO();
}
//----------------------------------------------------------------------------
void
TextNode::
setSize(unsigned int _size) {
size_ = _size; updateVBO();
}
//----------------------------------------------------------------------------
std::map<char, unsigned int>
TextNode::
createMap() {
......@@ -144,6 +220,7 @@ enter(GLState& /*_state*/, const DrawModes::DrawMode& /*_drawmode*/) {
void
TextNode::
leave(GLState& /*_state*/, const DrawModes::DrawMode& /*_drawmode*/) {
// restore the GLState as it was when entering TextNode
if (cullFaceEnabled_)
ACG::GLState::enable(GL_CULL_FACE);
if (!texture2dEnabled_)
......@@ -165,6 +242,8 @@ draw(GLState& _state, const DrawModes::DrawMode& /*_drawMode*/)
{
if (!text_.empty()) {
bindVBO();
// do not rotate the quads in this case
if (textMode_ == SCREEN_ALIGNED) {
_state.push_modelview_matrix();
Vec3d projected = _state.project(Vec3d(0.0, 0.0, 0.0));
......@@ -211,7 +290,7 @@ void
TextNode::setFont(const QFont& _font) {
qfont_ = QFont(_font);
initialised_ = false;
UpdateFont();
updateFont();
updateVBO();
}
......@@ -220,16 +299,19 @@ TextNode::setFont(const QFont& _font) {
void
TextNode::
UpdateFont() {
updateFont() {
// do not generate a new texture for every TextNode unless necessary
if (initialised_)
return;
QFontMetrics metric(qfont_);
int height = metric.height();
// ensure that the height of the texture is a power of 2
int heightPow2 = nearestPowerOfTwo(height);
int width = metric.maxWidth();
// ensure that the width of the texture is a power of 2
int widthPow2 = nearestPowerOfTwo(width);
imageWidth_ = widthPow2 * numberOfChars_;
......@@ -241,14 +323,19 @@ UpdateFont() {
| QPainter::TextAntialiasing);
painter.setFont(qfont_);
painter.setPen(color_);
// characters are drawn aligned to the left into the QImage finalImage next to each other
unsigned int i = 0;
for (char c = ' '; c < '~'; ++c, ++i) {
painter.drawText(i*widthPow2, 0, widthPow2, heightPow2, Qt::AlignLeft | Qt::AlignBottom, QString(c));
}
painter.end();
// convert finalImage to an OpenGL friendly format
finalImage = QGLWidget::convertToGLFormat(finalImage);
// delete the old texture if it exists
// and generate a new texture from finalImage
glDeleteTextures(1, &texture_);
glGenTextures(1, &texture_);
ACG::GLState::bindTexture(GL_TEXTURE_2D, texture_);
......@@ -274,7 +361,11 @@ updateVBO() {
vertexBuffer_.clear();
// generate a quad for each character
// generate a quad for each character next to each other
// *--*--*----*-*
// | | | | |
// | | | | |
// *--*--*----*-*
QFontMetrics metric(qfont_);
int maxWidth = metric.maxWidth();
int avgWidth = metric.averageCharWidth();
......@@ -300,7 +391,6 @@ updateVBO() {
// QFontMetrics does not seem to always give the correct width
// therefore we add a margin so that characters are not cut off
//if ( (leftBearing == 0) && (rightBearing == 0) ) {
if (leftBearing + rightBearing < 0.1*maxWidth) {
if (metricWidth + 0.25*maxWidth < maxWidth)
metricWidth += 0.25*maxWidth;
......@@ -311,6 +401,8 @@ updateVBO() {
}
float widthTx = (float) metricWidth / (float) imageWidth_;
// get the starting position of the character in the texture
// note that the characters are drawn aligned to the bottom left in in the texture
float leftTx = ((float) charToIndex_[text_[i]] ) / (float) numberOfChars_;
float rightTx = leftTx + widthTx;
......
......@@ -34,8 +34,8 @@
/*===========================================================================*\
* *
* $Revision$ *
* $Author$ *
* $Revision$ *
* $Author$ *
* $Date$ *
* *
\*===========================================================================*/
......@@ -75,9 +75,13 @@ namespace SceneGraph {
/** \class TextNode TextNode.hh <ACG/Scenegraph/TextNode.hh>
TextNode renders Text.
* TextNode can be used to display a string on quads in OpenGL. This string can be set with
* setText(std::string _text). A TextNode can be attached to a parent node by using the function
* BaseObjectData::addAdditionalNode. The quads can then be set to align to the parent by setting #textMode_
* to OBJECT_ALIGNED via the setRenderingMode(TextMode _textMode) function. Alternatively the quads can be aligned
* to the screen by setting #textMode_ to SCREEN_ALIGNED. The font that is used to display #text_ on the screen is stored
* in #qfont_, which can be set with the setFont(const QFont& _font) function. Finally the quads can be scaled by setting #size_
* via the setSize(unsigned int _size) function.
**/
class ACGDLLEXPORT TextNode : public BaseNode
......@@ -91,29 +95,12 @@ public:
/** default constructor
* @param _parent Define the parent Node this node gets attached to
* @param _fontfile Font File ( should include full path )
* @param _name Name of this Node
* @param _textMode Define the text rendering style ( see TextNode::TextMode )
*/
TextNode( std::string _fontFile,
BaseNode* _parent=0,
std::string _name="<TextNode>",
TextMode _textMode = SCREEN_ALIGNED)
: BaseNode(_parent, _name),
size_(1),
fontFile_(_fontFile),
textMode_(_textMode),
vbo_(0),
vertexBuffer_(0),
blendEnabled_(false),
texture2dEnabled_(false),
cullFaceEnabled_(false),
blendSrc_(0),
blendDest_(0)
{
UpdateFont();
updateVBO();
}
TextNode( BaseNode* _parent=0,
std::string _name="<TextNode>",
TextMode _textMode = SCREEN_ALIGNED);
/// destructor
~TextNode();
......@@ -138,65 +125,103 @@ public:
/** Set the rendering mode ( see TextNode::TextMode )
*/
void setRenderingMode(TextMode _textMode);
void setRenderingMode(TextMode _textMode) { textMode_ = _textMode; };
/// returns the rendering mode (SCREEN_ALIGNED or OBJECT_ALIGNED)
TextMode renderingMode();
TextMode renderingMode() { return textMode_; };
/// sets the string that will be rendered
void setText(std::string _text);
/// sets the text that will be rendered
void setText(std::string _text) {text_ = _text; updateVBO();};
/// sets the size by which the quads displaying the text will be scaled
void setSize(unsigned int _size);
/// sets the scaling size of the TextNode
void setSize(unsigned int _size) {size_ = _size; updateVBO();};
/// sets the font to be used
/// sets the font to be used for generating a texture with most characters of the chosen font
void setFont(const QFont& _font);
protected:
static void UpdateFont();
/**
* Generates a texture by drawing most characters into one texture.
* This texture is then used to draw single characters onto quads
*/
static void updateFont();
private:
/// returns the nearest greater power of 2 to num
static quint32 nearestPowerOfTwo(quint32 num);
/**
* generates a quad for each character in #text_ and also
* calculates the texture coordinates for each quad's character
*/
void updateVBO();
/// binds #vbo_ and sets the necessary OpenGL states
void bindVBO();
/// unbinds #vbo_
void unbindVBO();
/**
* Creates a map #charToIndex_ from most characters to an incrementing set of indices.
* These indices are used to create the texture coordinates in updateVBO().
*/
static std::map<char, unsigned int> createMap();
private:
/// scaling factor by which the quads in #vbo_ are scaled
unsigned int size_;
/// text to be displayed on quads in #vbo_
std::string text_;
std::string fontFile_;
/// current display mode of #text_ (SCREEN_ALIGNED or OBJECT_ALIGNED)
TextMode textMode_;
/**
* handle to the vertex buffer object, containing the quads on which the characters in
* #text_ are rendered
*/
GLuint vbo_;
/// buffer of vertex coordinates and texture coordinates of the quads
std::vector<GLfloat> vertexBuffer_;
/// stores if GL_BLEND was enabled on entering TextNode
bool blendEnabled_;
/// stores if GL_TEXTURE_2D was enabled on entering TextNode
bool texture2dEnabled_;
/// stores if GL_CULL_FACE was enabled on entering TextNode
bool cullFaceEnabled_;
/// stores the sfactor parameter of glBlendFunc on entering TextNode
GLint blendSrc_;
/// stores the dfactor parameter of glBlendFunc on entering TextNode
GLint blendDest_;
/// maps most readable characters to indices for texture coordinate calculation in updateVBO()
static std::map<char, unsigned int> charToIndex_;
/// font that is used to generate the texture in updateFont()
static QFont qfont_;
/// handle for the texture into which characters from #qfont_ are painted in updateFont()
static GLuint texture_;
/// width of the generated texture
static int imageWidth_;
/// number of characters that are drawn into the texture
static const int numberOfChars_ = 94;
/// this is used to ensure that the texture is only generated once when necessary
static bool initialised_;
/// color that is used to draw the characters into the texture in updateFont()
static QColor color_;
};
......
......@@ -432,21 +432,19 @@ void SkeletonObject::showIndices(bool _bVisible)
pSubMatNode = new ACG::SceneGraph::MaterialNode(pTransNode, nameSubMatNode.c_str());
addAdditionalNode(pSubMatNode, "SkeletonPlugin", nameSubMatNode.c_str());
}
// pSubMatNode->set_color(skeleton_->joint(i)->color());
#ifdef USE_FTGL
ACG::SceneGraph::TextNode *pTextNode = NULL;
if(!getAdditionalNode(pTextNode, "SkeletonPlugin", nameTextNode.c_str()))
{
pTextNode = new ACG::SceneGraph::TextNode(
(OpenFlipper::Options::fontsDirStr() + OpenFlipper::Options::dirSeparator() + "freefont" + OpenFlipper::Options:: dirSeparator() + "FreeSans.ttf").toStdString(),
pSubMatNode, nameTextNode.c_str(), ACG::SceneGraph::TextNode::SCREEN_ALIGNED);
addAdditionalNode(pTextNode, "SkeletonPlugin", nameTextNode.c_str());
}
pTextNode->setText(" " + nameJoint);
pTextNode->setSize(50);
pTextNode->multipassNodeSetActive(8, true);
#endif
// pSubMatNode->set_color(skeleton_->joint(i)->color());
ACG::SceneGraph::TextNode *pTextNode = NULL;
if(!getAdditionalNode(pTextNode, "SkeletonPlugin", nameTextNode.c_str()))
{
pTextNode = new ACG::SceneGraph::TextNode(pSubMatNode,
nameTextNode.c_str(),
ACG::SceneGraph::TextNode::SCREEN_ALIGNED);
addAdditionalNode(pTextNode, "SkeletonPlugin", nameTextNode.c_str());
}
pTextNode->setText(" " + nameJoint);
pTextNode->setSize(50);
pTextNode->multipassNodeSetActive(8, true);
}
//update the indices with the current animationhandle
......
......@@ -158,8 +158,7 @@ void RulerPlugin::slotMouseEvent(QMouseEvent* _event)
if (!object->getAdditionalNode(textNode_,name(),textNodeName_.c_str()))
{
textNode_ = new ACG::SceneGraph::TextNode((OpenFlipper::Options::fontsDirStr() + OpenFlipper::Options::dirSeparator() + "freefont" + OpenFlipper::Options::dirSeparator() + "FreeSans.ttf").toStdString(),
textTransformNode_,textNodeName_,ACG::SceneGraph::TextNode::OBJECT_ALIGNED);
textNode_ = new ACG::SceneGraph::TextNode(textTransformNode_,textNodeName_,ACG::SceneGraph::TextNode::OBJECT_ALIGNED);
object->addAdditionalNode(textNode_,name(),textNodeName_.c_str());
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment