Sign in to follow this  
legolas558

OpenGL and BMfont (released!)

Recommended Posts

I'm not sure what you're trying to acomplish, building a display list with all the characters doesn't make much sense to me. But then again, I do not know much about OpenGL. I think what you really need to do, is to create a display list for the text string you intend to print on the screen instead.

Anyway, it seems that you have misunderstood the meaning of x_advance. This should be used to update the cursor position after printing the character, it doesn't affect the position of the current character.

You may also want to use the kerning info, which for some fonts make a big difference. These values define an adjusted position of the characters for certain character pairs, e.g. 'i' and 'l' may need to be closer to each other than x_advance specify.

Regards,
Andreas

Share this post


Link to post
Share on other sites
As I said, I don't know OpenGL very well. If glCallList() can use the display list to get the quad that needs to be drawn and then position it correctly on the screen, then that sounds like a good idea. [smile]

The x,y, and offsets are correct. It's only the x_advance that was wrong. The tutorial does it correctly, as far as I can see.

Also that tutorial doesn't show you how to use the kerning information. Take a look at the other tutorial for that information.

About the image: Perhaps the texture is upside down? TGA files allow to specify the orientation of the textures, this could be the cause of the 'modern art'.

Regards,
Andreas

Share this post


Link to post
Share on other sites
Quote:
Original post by Deyja
Are you parsing the font file using boost::regex? No? Why not?


Because I have done it without. And without I don't have to include boost::regex.

Share this post


Link to post
Share on other sites
But boost makes the code SO AWESOME.

Probably won't make much sense out of context, but...


#pragma warning(disable:4786)

#include "font.h"
#include <boost/regex.hpp>
#include "vfs.h"
#include <boost/lexical_cast.hpp>
#include "log.h"
#include "sdl/sdl.h"

/* Regex's used for parsing font file. */
namespace
{

boost::regex Common(
"^common\\s+lineHeight=(\\d+)\\s+base=(\\d+)\\s+scaleW=(\\d+)\\s+scaleH=(\\d+)\\s+pages=(\\d+)\\s*$"
);

boost::regex Entry(
"^char\\s+id=(\\d+)\\s+x=(\\d+)\\s+y=(\\d+)\\s+width=(\\d+)\\s+height=(\\d+)\\s+xoffset=(-?\\d+)\\s+yoffset=(-?\\d+)\\s+xadvance=(\\d+)\\s+page=(\\d+)\\s*$"
);

std::string group(boost::match_results<std::string::const_iterator>& what, int index)
{
return std::string(what[index].first,what[index].second);
}

};

void Graphics::Font::Load(const std::string& filename)
{
pimple = boost::shared_ptr<FontImple>(new FontImple());

std::vector<std::string> v_lines;
{
System::File f(filename, System::File::READ | System::File::TEXT);
f.readAll(v_lines);
}

if (v_lines.size() < 1)
{
System::log << "Error loading font " << filename << ": Empty file?\n";
return;
}

boost::match_results<std::string::const_iterator> what;
if (!boost::regex_match(v_lines[0],what,Common))
{
System::log << "Error loading font " << filename << ": Error in header.\n";
return;
}

pimple->lineHeight = boost::lexical_cast<int>(group(what,1));
pimple->base = boost::lexical_cast<int>(group(what,2));
pimple->scale_width = boost::lexical_cast<int>(group(what,3));
pimple->scale_height = boost::lexical_cast<int>(group(what,4));
unsigned int nPages = boost::lexical_cast<int>(group(what,5));

for (unsigned int i = 0; i < nPages; ++i)
{
std::string t_fname = filename+"_";
if (i < 10) t_fname += "0";
t_fname += boost::lexical_cast<std::string>(i);
t_fname += ".tga";
pimple->pages.push_back(load_image(t_fname));
}

std::vector<std::string>::iterator line = v_lines.begin();
++line;
for (; line != v_lines.end(); ++line)
{
FontImple::CharInfo CI;
if (!boost::regex_match(*line,what,Entry)) {
System::log << "Error loading font " << filename << ": Line format mismatch.\n";
return;
}

unsigned int ID = boost::lexical_cast<int>(group(what,1));
pimple->chars[ID].x = boost::lexical_cast<int>(group(what,2));
pimple->chars[ID].y = boost::lexical_cast<int>(group(what,3));
pimple->chars[ID].width = boost::lexical_cast<int>(group(what,4));
pimple->chars[ID].height = boost::lexical_cast<int>(group(what,5));
pimple->chars[ID].x_offset = boost::lexical_cast<int>(group(what,6));
pimple->chars[ID].y_offset = boost::lexical_cast<int>(group(what,7));
pimple->chars[ID].x_advance = boost::lexical_cast<int>(group(what,8));
pimple->chars[ID].page = boost::lexical_cast<int>(group(what,9));
}
System::log << "Loaded font " << filename << ".\n";
}

void Graphics::Font::Draw(
const std::string& text,
int x, int y,
Graphics::Surface surface)
{
if (!pimple)
{
System::log << "Drawing with invalid font.\n";
return;
}

int LX = 0;
SDL_Rect source, dest;

for (unsigned int I = 0; I < text.size(); ++I)
{
if (text[I] >= 256) continue;

FontImple::CharInfo CI = pimple->chars[text[I]];
if (CI.page >= pimple->pages.size()) continue;

dest.x = x + (LX+CI.x_offset);
dest.y = y + (CI.y_offset);
dest.w = CI.width;
dest.h = CI.height;

source.x = CI.x;
source.y = CI.y;
source.w = CI.width;
source.h = CI.height;

SDL_BlitSurface(pimple->pages[CI.page].get(),&source,surface.get(),&dest);

LX += CI.x_advance;
}
}

Share this post


Link to post
Share on other sites
Maybe nicer to look, but it is AGES slower.
I have released the whole C source, and it doesn't need other stuff more than what is provided.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this