Initial work on billboard text

This commit is contained in:
Marianne Gagnon 2014-07-28 19:17:59 -04:00
parent 3db9b867a6
commit f803b01d10
4 changed files with 244 additions and 22 deletions

View File

@ -0,0 +1,119 @@
#include "graphics/stk_text_billboard.hpp"
#include "graphics/glwrap.hpp"
#include "graphics/shaders.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/stkbillboard.hpp"
#include "graphics/stkmeshscenenode.hpp"
#include "guiengine/engine.hpp"
#include "guiengine/scalable_font.hpp"
#include <SMesh.h>
#include <SMeshBuffer.h>
#include <ISceneManager.h>
using namespace irr;
STKTextBillboard::STKTextBillboard(core::stringw text, gui::ScalableFont* font,
const video::SColor& color, irr::scene::ISceneNode* parent,
irr::scene::ISceneManager* mgr, irr::s32 id,
const irr::core::vector3df& position, const irr::core::dimension2d<irr::f32>& size) : // TODO: use size or remove
IBillboardSceneNode(parent, mgr, id, position),
CBillboardSceneNode(parent, mgr, id, position, size, video::SColor(255, 255, 255, 255), video::SColor(255, 255, 255, 255))
{
font->doDraw(text, core::rect<s32>(0, 0, 1000, 1000), color, false, false, NULL, this);
const float scale = 0.05f;
scene::SMesh* mesh = new scene::SMesh();
std::map<video::ITexture*, scene::SMeshBuffer*> buffers;
for (unsigned int i = 0; i < m_chars.size(); i++)
{
core::vector3df char_pos(m_chars[i].m_destRect.UpperLeftCorner.X,
m_chars[i].m_destRect.UpperLeftCorner.Y, 0);
char_pos *= scale;
char_pos += position;
core::vector3df char_pos2(m_chars[i].m_destRect.LowerRightCorner.X,
m_chars[i].m_destRect.LowerRightCorner.Y, 0);
char_pos2 *= scale;
char_pos2 += position;
core::dimension2di char_size_i = m_chars[i].m_destRect.getSize();
core::dimension2df char_size(char_size_i.Width*scale, char_size_i.Height*scale);
std::map<video::ITexture*, scene::SMeshBuffer*>::iterator map_itr = buffers.find(m_chars[i].m_texture);
scene::SMeshBuffer* buffer;
if (map_itr == buffers.end())
{
buffer = new scene::SMeshBuffer();
buffer->getMaterial().setTexture(0, m_chars[i].m_texture);
buffer->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
buffers[m_chars[i].m_texture] = buffer;
}
else
{
buffer = map_itr->second;
}
float tex_width = m_chars[i].m_texture->getSize().Width;
float tex_height = m_chars[i].m_texture->getSize().Height;
video::S3DVertex vertices[] =
{
video::S3DVertex(char_pos.X, char_pos.Y, 0.0f,
0.0f, 0.0f, 1.0f,
video::SColor(255, 255, 255, 255),
m_chars[i].m_sourceRect.UpperLeftCorner.X / tex_width,
m_chars[i].m_sourceRect.LowerRightCorner.Y / tex_height),
video::S3DVertex(char_pos2.X, char_pos.Y, 0.0f,
0.0f, 0.0f, 1.0f,
video::SColor(255, 255, 255, 255),
m_chars[i].m_sourceRect.LowerRightCorner.X / tex_width,
m_chars[i].m_sourceRect.LowerRightCorner.Y / tex_height),
video::S3DVertex(char_pos2.X, char_pos2.Y, 0.0f,
0.0f, 0.0f, 1.0f,
video::SColor(255, 255, 255, 255),
m_chars[i].m_sourceRect.LowerRightCorner.X / tex_width,
m_chars[i].m_sourceRect.UpperLeftCorner.Y / tex_height),
video::S3DVertex(char_pos.X, char_pos2.Y, 0.0f,
0.0f, 0.0f, 1.0f,
video::SColor(255, 255, 255, 255),
m_chars[i].m_sourceRect.UpperLeftCorner.X / tex_width,
m_chars[i].m_sourceRect.UpperLeftCorner.Y / tex_height)
};
irr::u16 indices[] = { 2, 1, 0, 3, 2, 0 };
buffer->append(vertices, 4, indices, 6);
}
for (std::map<video::ITexture*, scene::SMeshBuffer*>::iterator map_itr = buffers.begin();
map_itr != buffers.end(); map_itr++)
{
mesh->addMeshBuffer(map_itr->second);
map_itr->second->drop();
}
STKMeshSceneNode* stk_mesh = new STKMeshSceneNode(mesh,
parent, irr_driver->getSceneManager(), -1,
position, core::vector3df(0.0f, 0.0f, 0.0f), core::vector3df(1.0f, 1.0f, 1.0f));
stk_mesh->setAutomaticCulling(0);
}
void STKTextBillboard::render()
{
}
void STKTextBillboard::collectChar(video::ITexture* texture,
const core::rect<s32>& destRect,
const core::rect<s32>& sourceRect,
const video::SColor* const colors)
{
m_chars.push_back(STKTextBillboardChar(texture, destRect, sourceRect, colors));
}

View File

@ -0,0 +1,58 @@
#ifndef STK_TEXT_BILLBOARD_HPP
#define STK_TEXT_BILLBOARD_HPP
#include "../lib/irrlicht/source/Irrlicht/CBillboardSceneNode.h"
#include <IBillboardSceneNode.h>
#include <irrTypes.h>
#include "guiengine/scalable_font.hpp"
class STKTextBillboardChar
{
public:
irr::video::ITexture* m_texture;
irr::core::rect<irr::s32> m_destRect;
irr::core::rect<irr::s32> m_sourceRect;
irr::video::SColor m_colors[4];
STKTextBillboardChar(irr::video::ITexture* texture,
const irr::core::rect<irr::s32>& destRect,
const irr::core::rect<irr::s32>& sourceRect,
const irr::video::SColor* const colors)
{
m_texture = texture;
m_destRect = destRect;
m_sourceRect = sourceRect;
if (colors == NULL)
{
m_colors[0] = m_colors[1] = m_colors[2] = m_colors[3] = NULL;
}
else
{
m_colors[0] = colors[0];
m_colors[1] = colors[1];
m_colors[2] = colors[2];
m_colors[3] = colors[3];
}
}
};
class STKTextBillboard : public irr::scene::CBillboardSceneNode, irr::gui::FontCharCollector
{
std::vector<STKTextBillboardChar> m_chars;
public:
STKTextBillboard(irr::core::stringw text, irr::gui::ScalableFont* font,
const irr::video::SColor& color, irr::scene::ISceneNode* parent,
irr::scene::ISceneManager* mgr, irr::s32 id,
const irr::core::vector3df& position,
const irr::core::dimension2d<irr::f32>& size);
virtual void render();
virtual void collectChar(irr::video::ITexture* texture,
const irr::core::rect<irr::s32>& destRect,
const irr::core::rect<irr::s32>& sourceRect,
const irr::video::SColor* const colors);
};
#endif

View File

@ -463,6 +463,14 @@ core::dimension2d<u32> ScalableFont::getDimension(const wchar_t* text) const
return dim;
}
void ScalableFont::draw(const core::stringw& text,
const core::rect<s32>& position, video::SColor color,
bool hcenter, bool vcenter,
const core::rect<s32>* clip)
{
doDraw(text, position, color, hcenter, vcenter, clip, NULL);
}
void ScalableFont::draw(const core::stringw& text,
const core::rect<s32>& position, video::SColor color,
bool hcenter, bool vcenter,
@ -471,16 +479,17 @@ void ScalableFont::draw(const core::stringw& text,
bool previousRTL = m_rtl;
if (ignoreRTL) m_rtl = false;
draw(text, position, color, hcenter, vcenter, clip);
doDraw(text, position, color, hcenter, vcenter, clip, NULL);
if (ignoreRTL) m_rtl = previousRTL;
}
//! draws some text and clips it to the specified rectangle if wanted
void ScalableFont::draw(const core::stringw& text,
const core::rect<s32>& position, video::SColor color,
bool hcenter, bool vcenter,
const core::rect<s32>* clip)
void ScalableFont::doDraw(const core::stringw& text,
const core::rect<s32>& position, video::SColor color,
bool hcenter, bool vcenter,
const core::rect<s32>* clip,
FontCharCollector* charCollector)
{
if (!Driver) return;
@ -637,7 +646,7 @@ void ScalableFont::draw(const core::stringw& text,
}
}
if (m_black_border)
if (m_black_border && charCollector == NULL)
{
// draw black border
video::SColor black(color.getAlpha(),0,0,0);
@ -658,23 +667,45 @@ void ScalableFont::draw(const core::stringw& text,
if (fallback[n])
{
// draw text over
// TODO: don't hardcode colors?
static video::SColor orange(color.getAlpha(), 255, 100, 0);
static video::SColor yellow(color.getAlpha(), 255, 220, 15);
video::SColor title_colors[] = {yellow, orange, orange, yellow};
draw2DImage(texture,
dest,
source,
clip,
title_colors, true);
if (charCollector != NULL)
{
charCollector->collectChar(texture,
dest,
source,
title_colors);
}
else
{
draw2DImage(texture,
dest,
source,
clip,
title_colors, true);
}
}
else
{
draw2DImage(texture,
dest,
source,
clip,
color, true);
if (charCollector != NULL)
{
video::SColor colors[] = { color, color, color, color };
charCollector->collectChar(texture,
dest,
source,
colors);
}
else
{
draw2DImage(texture,
dest,
source,
clip,
color, true);
}
#ifdef FONT_DEBUG
driver->draw2DLine(core::position2d<s32>(dest.UpperLeftCorner.X, dest.UpperLeftCorner.Y),
core::position2d<s32>(dest.UpperLeftCorner.X, dest.LowerRightCorner.Y),

View File

@ -26,6 +26,7 @@ namespace video
{
class IVideoDriver;
class IImage;
class ITexture;
}
namespace gui
@ -33,6 +34,14 @@ namespace gui
class IGUIEnvironment;
class FontCharCollector
{
public:
virtual void collectChar(video::ITexture* texture, const core::rect<s32>& destRect,
const core::rect<s32>& sourceRect, const video::SColor* const colors) = 0;
};
class ScalableFont : public IGUIFontBitmap
{
float m_scale;
@ -101,12 +110,17 @@ public:
//! draws an text and clips it to the specified rectangle if wanted
virtual void draw(const core::stringw& text, const core::rect<s32>& position,
video::SColor color, bool hcenter=false,
bool vcenter=false, const core::rect<s32>* clip=0);
video::SColor color, bool hcenter = false,
bool vcenter = false, const core::rect<s32>* clip = 0);
virtual void draw(const core::stringw& text, const core::rect<s32>& position,
video::SColor color, bool hcenter,
bool vcenter, const core::rect<s32>* clip, bool ignoreRTL);
void draw(const core::stringw& text, const core::rect<s32>& position,
video::SColor color, bool hcenter,
bool vcenter, const core::rect<s32>* clip, bool ignoreRTL);
void doDraw(const core::stringw& text, const core::rect<s32>& position,
video::SColor color, bool hcenter,
bool vcenter, const core::rect<s32>* clip,
FontCharCollector* charCollector = NULL);
//! returns the dimension of a text
virtual core::dimension2d<u32> getDimension(const wchar_t* text) const;