Jump to content

  • Log In with Google      Sign In   
  • Create Account

Banner advertising on our site currently available from just $5!


1. Learn about the promo. 2. Sign up for GDNet+. 3. Set up your advert!


Katz

Member Since 21 Jun 2011
Offline Last Active Jun 22 2011 12:56 PM

Posts I've Made

In Topic: Problem with lesson 43

22 June 2011 - 12:58 PM

OK, I solved my own problem, after much looking around.
I had two main problems: One was that my texture coordinates were entered into integers, although they are supposed to by smaller than 1. (Two days for this problem... *facepalm*)
The other was that I am using a different coordinate system: My ordinate axis runs from top to bottom and not bottom to top.

Anyway, working code, if it may help anybody:
#include <SDL.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <ft2build.h>
#include FT_FREETYPE_H
#include <vector>
#include <string>
#include <iostream>

using namespace std;

struct font_data
{
	int h;
	GLuint *textures;
	GLuint listBase;

	void init(string fontName, unsigned int h); //create font of required height
	void clean();                           	//clean font data
};

void write(const font_data &ft_font, int x, int y, string text);

//get power of two right above given number
inline int nextP2(int nb)
{
	int ret=1;
	while(ret < nb)
    	ret *= 2;
	return ret;
}

//create a display lit corresponding to the given character
void makeDList(FT_Face font, unsigned char ch, GLuint listBase, GLuint *texBase)
{
	if(FT_Load_Char(font, ch, FT_LOAD_RENDER))
    	cout << "FT_Load_Char failed in makeDList." <<  endl;
	FT_GlyphSlot glyph = font->glyph;
	FT_Bitmap &bitmap = glyph->bitmap;

	//get required width and height to get correct texture size
	int width = nextP2(bitmap.width);
	int height = nextP2(bitmap.rows);

	GLubyte *expandedData = new GLubyte [2*width*height];

	for(int j=0;j<height;j++)
	{
    	for(int i=0;i<width;i++)
    	{
        	expandedData[2*(i+j*width)] = 255;
        	expandedData[2*(i+j*width)+1] = (i>=bitmap.width || j>=bitmap.rows) ? 0 : bitmap.buffer[i+bitmap.width*j];
    	}
	}

	glBindTexture(GL_TEXTURE_2D, texBase[ch]);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR);

	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, expandedData);

	delete [] expandedData;

	glNewList(listBase + ch, GL_COMPILE);

    	glBindTexture(GL_TEXTURE_2D, texBase[ch]);

    	glPushMatrix();
    	glTranslatef(glyph->bitmap_left,0,0); //shift character to have right amount of space before
    	glTranslatef(0, (font->bbox.yMax - glyph->metrics.horiBearingY)/64,0); //move down a little if previous line has lower character
    	double x = (double)bitmap.width /(double)width; //take empty space around char into account
    	double y = (double)bitmap.rows / (double)height;

    	glBegin(GL_QUADS);
    	glTexCoord2d(0,y);
        	glVertex2f(0,bitmap.rows);
    	glTexCoord2d(0,0);
        	glVertex2f(0,0);
    	glTexCoord2d(x,0);
        	glVertex2f(bitmap.width,0);
    	glTexCoord2d(x,y);
        	glVertex2f(bitmap.width,bitmap.rows);
    	glEnd();
    	glPopMatrix();
    	glTranslatef(glyph->metrics.horiAdvance/64,0,0);

	glEndList();
}

void font_data::init(string fontName, unsigned int h)
{
	textures = new GLuint[128];
	this->h=h;

	FT_Library library;
	if(FT_Init_FreeType(&library))
    	cout << "Could not initialize Freetype library" << endl;

	FT_Face font;
	if(FT_New_Face(library, fontName.c_str(), 0, &font))
    	cout << "Could not open  font \"" <<fontName<<"\"."<<endl;
	FT_Set_Char_Size(font, h*64,h*64,96,96); //set font size

	//allocate resources for textures and display lists
	listBase=glGenLists(128);
	glGenTextures(128,textures);

	//create each of the fonts display lists
	for(unsigned char i=0;i<128;i++)
    	makeDList(font,i,listBase,textures);

	FT_Done_Face(font);
	FT_Done_FreeType(library);
}

void font_data::clean()
{
	glDeleteLists(listBase,128);
	glDeleteTextures(128,textures);
	delete [] textures;
}

void write(const font_data &ft_font, int x, int y, string text)
{
	GLuint font = ft_font.listBase;
	glListBase(font);

	glPushMatrix();
	glTranslatef(x,y,0); //move to text
	glCallLists(text.length(), GL_UNSIGNED_BYTE,text.c_str());
	glPopMatrix();
}

int main ( int argc, char** argv )
{
	SDL_Init( SDL_INIT_VIDEO );
	SDL_SetVideoMode(800, 600, 32, SDL_OPENGL);
	//set openGL parameters
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluOrtho2D(0,800,600,0);
	glDisable(GL_DEPTH_TEST); //depth buffering
	glEnable(GL_TEXTURE_2D); //texture using
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);

	font_data myFont;
	myFont.init("../TD/fonts/jester.ttf", 20);

	SDL_Event event;
	bool quit = false;
	while(!quit)
	{
    	glClear(GL_COLOR_BUFFER_BIT);

    	glColor3ub(255,255,255);
    	glDisable(GL_TEXTURE_2D);
    	glBegin(GL_QUADS);
        	glVertex2d(0,0);
        	glVertex2d(800,0);
        	glVertex2d(800,600);
        	glVertex2d(0,600);
    	glEnd();
    	glEnable(GL_TEXTURE_2D);
    	glColor3ub(180,180,0);
    	write(myFont,200,300, "Hello World!");

    	glFlush();
    	SDL_GL_SwapBuffers();

    	while (SDL_PollEvent(&event))
    	{
        	if(event.type == SDL_QUIT || (event.type == SDL_KEYDOWN && (event.key.keysym.sym == SDLK_ESCAPE || event.key.keysym.sym == SDLK_RETURN)))
            	quit=true;
    	}
	}

	myFont.clean();
	SDL_Quit();
}

PARTNERS