Best way to rotate a ITextSceneNode

You are an experienced programmer and have a problem with the engine, shaders, or advanced effects? Here you'll get answers.
No questions about C++ programming or topics which are answered in the tutorials!
Post Reply
maxme
Posts: 2
Joined: Tue Mar 23, 2010 4:49 pm

Best way to rotate a ITextSceneNode

Post by maxme »

Hi,

I'm playing with Irrlicht since a few weeks. I'm trying to add some text in my game so I used a ITextSceneNode with my own font and everything is fine, I can move it where I want.

I tried to rotate it as I rotate my others nodes using the "setRotation(vector3df&)" method and it doesn't work. So I read the code of CSpriteTextNode.cpp and I figured out that it called the Font->draw() method that doesn't take the RelativeRotation of my node into account (it seems that it projects my world coordinate to the absolute screen coordinate system and just draw it as it without applying any transformations).

So I want to add the possibility to draw text like ITextSceneNode does but with the use of basics transformation (rotation / scaling). I'm writing here to ask you how I can do that ?

I think about sub-classing CSpriteTextNode and change the render() method but it seems all the drawing stuff is done by "CGUIFont->draw()", what do you experts think about it ? Or maybe I'm completely missing something ?

Thanks for reading me, and thanks for Irrlicht (I'm quite new but the more I play with it, the more I like it).
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

I don't think that it is implemented so far. The 2d methods are basically rotation unaware. What you can do is to render the font to a plane and display that plane at the position and rotation you want.
sudi
Posts: 1686
Joined: Fri Aug 26, 2005 8:38 pm

Post by sudi »

This should help ya.

Edit: this code works like you want it. But when using it with other render Targets. like my deferred renderer the text is flipped upside down. dunno why.

example usage:

Code: Select all

CTextNode* text = new CTextNode(gui, smgr->getRootSceneNode(), smgr);
    text->setText("Hello my friend!");
    text->setPosition(irr::core::vector3df(0,20,0));
Header:

Code: Select all

#ifndef CTEXTNODE_H
#define CTEXTNODE_H

#include <irrlicht.h>

class CTextNode : public irr::scene::ISceneNode
{
    public:
        /** Default constructor */
        CTextNode(irr::gui::IGUIEnvironment* gui, irr::scene::ISceneNode* parent, irr::scene::ISceneManager* mgr, irr::s32 id=-1,
				const irr::core::vector3df& position = irr::core::vector3df(0,0,0),
				const irr::core::vector3df& rotation = irr::core::vector3df(0,0,0),
				const irr::core::vector3df& scale = irr::core::vector3df(1.0f, 1.0f, 1.0f));
        /** Default destructor */
        virtual ~CTextNode();

        //SceneNode
        void OnRegisterSceneNode(void);
        void OnAnimate(irr::u32 timeMs);
        void render(void);
        const irr::core::aabbox3d<irr::f32>& getBoundingBox(void) const;
        irr::video::SMaterial& getMaterial(irr::u32 num);
        irr::u32 getMaterialCount() const;

        void setText(const irr::c8* text);
        void setColor(const irr::video::SColor& color);
    protected:
        irr::core::stringw Text;
        irr::core::dimension2d<irr::u32> TextDimension;
        irr::video::ITexture* TextTexture;
        irr::video::SColor TextColor;

        irr::scene::SMeshBuffer* MeshBuffer;
        irr::video::SMaterial Material;
        irr::core::aabbox3d<irr::f32> Box;

        bool Redraw;
        irr::gui::IGUIEnvironment* Gui;
    private:
};

#endif // CTEXTNODE_H
Source:

Code: Select all

#include "irr/CTextNode.h"

CTextNode::CTextNode(irr::gui::IGUIEnvironment* gui, irr::scene::ISceneNode* parent, irr::scene::ISceneManager* mgr, irr::s32 id,
                     const irr::core::vector3df& position,
                     const irr::core::vector3df& rotation,
                     const irr::core::vector3df& scale) : irr::scene::ISceneNode(parent, mgr, id, position, rotation, scale)
{
    //ctor
    MeshBuffer = new irr::scene::SMeshBuffer;
    MeshBuffer->Vertices.push_back(irr::video::S3DVertex(-0.5, 0.5, 0.0, 0.0, 0.0, -1.0, irr::video::SColor(255,255,255,255), 0.01, 0.01));
    MeshBuffer->Vertices.push_back(irr::video::S3DVertex(0.5, 0.5, 0.0, 0.0, 0.0, -1.0, irr::video::SColor(255,255,255,255), 0.9999, 0.01));
    MeshBuffer->Vertices.push_back(irr::video::S3DVertex(0.5, -0.5, 0.0, 0.0, 0.0, -1.0, irr::video::SColor(255,255,255,255), 0.9999, 0.9999));
    MeshBuffer->Vertices.push_back(irr::video::S3DVertex(-0.5, -0.5, 0.0, 0.0, 0.0, -1.0, irr::video::SColor(255,255,255,255), 0.01, 0.9999));
    MeshBuffer->Indices.push_back(0);
    MeshBuffer->Indices.push_back(1);
    MeshBuffer->Indices.push_back(2);
    MeshBuffer->Indices.push_back(2);
    MeshBuffer->Indices.push_back(3);
    MeshBuffer->Indices.push_back(0);
    MeshBuffer->recalculateBoundingBox();

    Gui = gui;
    TextTexture = NULL;
    TextColor = irr::video::SColor(255,255,255,255);
    Redraw = true;

    Material.MaterialType = irr::video::EMT_TRANSPARENT_ALPHA_CHANNEL;
    Material.Lighting = false;
    Material.BackfaceCulling = false;
}

CTextNode::~CTextNode()
{
    //dtor
}

void CTextNode::setText(const irr::c8* text)
{
    Text = text;
    Redraw = true;
}

void CTextNode::setColor(const irr::video::SColor& color)
{
    TextColor = color;
}

void CTextNode::OnRegisterSceneNode()
{
    if (isVisible())
    {
        SceneManager->registerNodeForRendering(this, irr::scene::ESNRP_TRANSPARENT);
        if (Redraw)
        {
            SceneManager->getVideoDriver()->removeTexture(TextTexture);
            TextDimension = Gui->getSkin()->getFont()->getDimension(Text.c_str());
            irr::core::dimension2d<irr::u32> texdim = TextDimension;
            texdim.Width += Gui->getSkin()->getFont()->getKerningWidth()+2;
            texdim.Height += Gui->getSkin()->getFont()->getKerningHeight()+2;
            if (TextDimension.Width != 0 && TextDimension.Height != 0)
            {

                TextTexture = SceneManager->getVideoDriver()->addRenderTargetTexture(texdim, "TextNodeTexture", irr::video::ECF_A8R8G8B8);
                SceneManager->getVideoDriver()->setRenderTarget(TextTexture, true, true, irr::video::SColor(0,0,0,0));
                SceneManager->getVideoDriver()->setMaterial(irr::video::SMaterial());
                Gui->getSkin()->getFont()->draw(Text.c_str(), irr::core::rect<irr::s32>(0, 0, TextDimension.Width, TextDimension.Height), TextColor);
                SceneManager->getVideoDriver()->setMaterial(irr::video::SMaterial());
                SceneManager->getVideoDriver()->setRenderTarget(0, false, false);
                SceneManager->getVideoDriver()->setMaterial(irr::video::SMaterial());
                Material.setTexture(0, TextTexture);
            }
            Redraw = false;
        }
    }
    irr::scene::ISceneNode::OnRegisterSceneNode();
}

void CTextNode::OnAnimate(irr::u32 timeMs)
{

    irr::scene::ISceneNode::OnAnimate(timeMs);
}

void CTextNode::render(void)
{
    irr::video::IVideoDriver* driver = SceneManager->getVideoDriver();

    irr::core::matrix4 trans = getAbsoluteTransformation();
    irr::core::matrix4 scale;
    scale.setScale(irr::core::vector3df(TextDimension.Width, TextDimension.Height, 0.0));
    trans *= scale;

    driver->setTransform(irr::video::ETS_WORLD, trans);
    driver->draw3DBox(getTransformedBoundingBox());
    driver->setMaterial(Material);
    driver->drawMeshBuffer(MeshBuffer);
    driver->setMaterial(irr::video::SMaterial());
}

const irr::core::aabbox3d<irr::f32>& CTextNode::getBoundingBox(void) const
{
    return MeshBuffer->getBoundingBox();
}

irr::video::SMaterial& CTextNode::getMaterial(irr::u32 num)
{
    return Material;
}

irr::u32 CTextNode::getMaterialCount() const
{
    return 1;
}
We're programmers. Programmers are, in their hearts, architects, and the first thing they want to do when they get to a site is to bulldoze the place flat and build something grand. We're not excited by renovation:tinkering,improving,planting flower beds.
maxme
Posts: 2
Joined: Tue Mar 23, 2010 4:49 pm

Post by maxme »

Thanks a lot for the code, it works exactly as I wanted !
jsyzljj
Posts: 2
Joined: Mon Dec 12, 2016 1:23 am

Re:The text looks not clear on the screen.

Post by jsyzljj »

Sudi wrote:This should help ya.

Edit: this code works like you want it. But when using it with other render Targets. like my deferred renderer the text is flipped upside down. dunno why.

example usage:

Code: Select all

 
CTextNode* text = new CTextNode(gui, smgr->getRootSceneNode(), smgr);
    text->setText("Hello my friend!");
    text->setPosition(irr::core::vector3df(0,20,0));
 
Header:

Code: Select all

 
#ifndef CTEXTNODE_H
#define CTEXTNODE_H
 
#include <irrlicht.h>
 
class CTextNode : public irr::scene::ISceneNode
{
    public:
        /** Default constructor */
        CTextNode(irr::gui::IGUIEnvironment* gui, irr::scene::ISceneNode* parent, irr::scene::ISceneManager* mgr, irr::s32 id=-1,
                const irr::core::vector3df& position = irr::core::vector3df(0,0,0),
                const irr::core::vector3df& rotation = irr::core::vector3df(0,0,0),
                const irr::core::vector3df& scale = irr::core::vector3df(1.0f, 1.0f, 1.0f));
        /** Default destructor */
        virtual ~CTextNode();
 
        //SceneNode
        void OnRegisterSceneNode(void);
        void OnAnimate(irr::u32 timeMs);
        void render(void);
        const irr::core::aabbox3d<irr::f32>& getBoundingBox(void) const;
        irr::video::SMaterial& getMaterial(irr::u32 num);
        irr::u32 getMaterialCount() const;
 
        void setText(const irr::c8* text);
        void setColor(const irr::video::SColor& color);
    protected:
        irr::core::stringw Text;
        irr::core::dimension2d<irr::u32> TextDimension;
        irr::video::ITexture* TextTexture;
        irr::video::SColor TextColor;
 
        irr::scene::SMeshBuffer* MeshBuffer;
        irr::video::SMaterial Material;
        irr::core::aabbox3d<irr::f32> Box;
 
        bool Redraw;
        irr::gui::IGUIEnvironment* Gui;
    private:
};
 
#endif // CTEXTNODE_H
 
Source:

Code: Select all

 
#include "irr/CTextNode.h"
 
CTextNode::CTextNode(irr::gui::IGUIEnvironment* gui, irr::scene::ISceneNode* parent, irr::scene::ISceneManager* mgr, irr::s32 id,
                     const irr::core::vector3df& position,
                     const irr::core::vector3df& rotation,
                     const irr::core::vector3df& scale) : irr::scene::ISceneNode(parent, mgr, id, position, rotation, scale)
{
    //ctor
    MeshBuffer = new irr::scene::SMeshBuffer;
    MeshBuffer->Vertices.push_back(irr::video::S3DVertex(-0.5, 0.5, 0.0, 0.0, 0.0, -1.0, irr::video::SColor(255,255,255,255), 0.01, 0.01));
    MeshBuffer->Vertices.push_back(irr::video::S3DVertex(0.5, 0.5, 0.0, 0.0, 0.0, -1.0, irr::video::SColor(255,255,255,255), 0.9999, 0.01));
    MeshBuffer->Vertices.push_back(irr::video::S3DVertex(0.5, -0.5, 0.0, 0.0, 0.0, -1.0, irr::video::SColor(255,255,255,255), 0.9999, 0.9999));
    MeshBuffer->Vertices.push_back(irr::video::S3DVertex(-0.5, -0.5, 0.0, 0.0, 0.0, -1.0, irr::video::SColor(255,255,255,255), 0.01, 0.9999));
    MeshBuffer->Indices.push_back(0);
    MeshBuffer->Indices.push_back(1);
    MeshBuffer->Indices.push_back(2);
    MeshBuffer->Indices.push_back(2);
    MeshBuffer->Indices.push_back(3);
    MeshBuffer->Indices.push_back(0);
    MeshBuffer->recalculateBoundingBox();
 
    Gui = gui;
    TextTexture = NULL;
    TextColor = irr::video::SColor(255,255,255,255);
    Redraw = true;
 
    Material.MaterialType = irr::video::EMT_TRANSPARENT_ALPHA_CHANNEL;
    Material.Lighting = false;
    Material.BackfaceCulling = false;
}
 
CTextNode::~CTextNode()
{
    //dtor
}
 
void CTextNode::setText(const irr::c8* text)
{
    Text = text;
    Redraw = true;
}
 
void CTextNode::setColor(const irr::video::SColor& color)
{
    TextColor = color;
}
 
void CTextNode::OnRegisterSceneNode()
{
    if (isVisible())
    {
        SceneManager->registerNodeForRendering(this, irr::scene::ESNRP_TRANSPARENT);
        if (Redraw)
        {
            SceneManager->getVideoDriver()->removeTexture(TextTexture);
            TextDimension = Gui->getSkin()->getFont()->getDimension(Text.c_str());
            irr::core::dimension2d<irr::u32> texdim = TextDimension;
            texdim.Width += Gui->getSkin()->getFont()->getKerningWidth()+2;
            texdim.Height += Gui->getSkin()->getFont()->getKerningHeight()+2;
            if (TextDimension.Width != 0 && TextDimension.Height != 0)
            {
 
                TextTexture = SceneManager->getVideoDriver()->addRenderTargetTexture(texdim, "TextNodeTexture", irr::video::ECF_A8R8G8B8);
                SceneManager->getVideoDriver()->setRenderTarget(TextTexture, true, true, irr::video::SColor(0,0,0,0));
                SceneManager->getVideoDriver()->setMaterial(irr::video::SMaterial());
                Gui->getSkin()->getFont()->draw(Text.c_str(), irr::core::rect<irr::s32>(0, 0, TextDimension.Width, TextDimension.Height), TextColor);
                SceneManager->getVideoDriver()->setMaterial(irr::video::SMaterial());
                SceneManager->getVideoDriver()->setRenderTarget(0, false, false);
                SceneManager->getVideoDriver()->setMaterial(irr::video::SMaterial());
                Material.setTexture(0, TextTexture);
            }
            Redraw = false;
        }
    }
    irr::scene::ISceneNode::OnRegisterSceneNode();
}
 
void CTextNode::OnAnimate(irr::u32 timeMs)
{
 
    irr::scene::ISceneNode::OnAnimate(timeMs);
}
 
void CTextNode::render(void)
{
    irr::video::IVideoDriver* driver = SceneManager->getVideoDriver();
 
    irr::core::matrix4 trans = getAbsoluteTransformation();
    irr::core::matrix4 scale;
    scale.setScale(irr::core::vector3df(TextDimension.Width, TextDimension.Height, 0.0));
    trans *= scale;
 
    driver->setTransform(irr::video::ETS_WORLD, trans);
    driver->draw3DBox(getTransformedBoundingBox());
    driver->setMaterial(Material);
    driver->drawMeshBuffer(MeshBuffer);
    driver->setMaterial(irr::video::SMaterial());
}
 
const irr::core::aabbox3d<irr::f32>& CTextNode::getBoundingBox(void) const
{
    return MeshBuffer->getBoundingBox();
}
 
irr::video::SMaterial& CTextNode::getMaterial(irr::u32 num)
{
    return Material;
}
 
irr::u32 CTextNode::getMaterialCount() const
{
    return 1;
}
 
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Best way to rotate a ITextSceneNode

Post by CuteAlien »

jsyzljj: Did you change anything or just copy-paste a post here? Asking because new users which copy-paste posts are usually bots ... and right now I'm not sure yet if you are one or not (as your other posts looked rather normal...).
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Xeverous
Posts: 11
Joined: Tue Jan 24, 2017 7:25 pm

Re: Best way to rotate a ITextSceneNode

Post by Xeverous »

Seems it was just reposted to highlight code the C++ way, not as raw text
Post Reply