[Add] gl_print (FreeType fonts).
This commit is contained in:
parent
d39e7925ea
commit
e8ed98b69d
@ -12,8 +12,9 @@ DATAFILES = $(shell find ../gfx/ ../dat/ -name '*.png' -o -name '*.xml' -print)
|
|||||||
CLUA = -I/usr/include/lua5.1
|
CLUA = -I/usr/include/lua5.1
|
||||||
CSDL = `sdl-config --cflags`
|
CSDL = `sdl-config --cflags`
|
||||||
CXML = `xml2-config --cflags`
|
CXML = `xml2-config --cflags`
|
||||||
|
CTTF = `freetype-config --cflags`
|
||||||
CGL =
|
CGL =
|
||||||
CFLAGS = -Wall $(CLUA) $(CSDL) $(CXML) $(CGL) $(VERSION)
|
CFLAGS = -Wall $(CLUA) $(CSDL) $(CXML) $(CTTF) $(CGL) $(VERSION)
|
||||||
ifdef DEBUG
|
ifdef DEBUG
|
||||||
CFLAGS += -g3 -DDEBUG
|
CFLAGS += -g3 -DDEBUG
|
||||||
else
|
else
|
||||||
@ -23,8 +24,9 @@ endif
|
|||||||
LDLUA = -llua5.1
|
LDLUA = -llua5.1
|
||||||
LDSDL = `sdl-config --libs` -lSDL_image
|
LDSDL = `sdl-config --libs` -lSDL_image
|
||||||
LDXML = `xml2-config --libs`
|
LDXML = `xml2-config --libs`
|
||||||
|
LDTTF = `freetype-config --libs`
|
||||||
LDGL = -lGL
|
LDGL = -lGL
|
||||||
LDFLAGS = -lm $(LDLUA) $(LDSDL) $(LDXML) $(LDGL)
|
LDFLAGS = -lm $(LDLUA) $(LDSDL) $(LDXML) $(LDTTF) $(LDGL)
|
||||||
|
|
||||||
%.o: ../src/%.c
|
%.o: ../src/%.c
|
||||||
@gcc -c $(CFLAGS) -o $@ $<
|
@gcc -c $(CFLAGS) -o $@ $<
|
||||||
|
34
src/main.c
34
src/main.c
@ -15,23 +15,27 @@
|
|||||||
#include "joystick.h"
|
#include "joystick.h"
|
||||||
#include "space.h"
|
#include "space.h"
|
||||||
#include "rng.h"
|
#include "rng.h"
|
||||||
|
#include "ai.h"
|
||||||
#include "pilot.h"
|
#include "pilot.h"
|
||||||
|
|
||||||
#define CONF_FILE "conf"
|
#define CONF_FILE "conf"
|
||||||
|
|
||||||
|
static gl_font fdefault;
|
||||||
|
|
||||||
static int quit = 0;
|
static int quit = 0;
|
||||||
|
|
||||||
static unsigned int time = 0;
|
static unsigned int time = 0;
|
||||||
|
|
||||||
// Prototypes.
|
// Prototypes.
|
||||||
|
|
||||||
void print_usage(char** argv);
|
static void print_usage(char** argv);
|
||||||
|
static void display_fps(const double dt);
|
||||||
|
|
||||||
// Update.
|
// Update.
|
||||||
static void update_all(void);
|
static void update_all(void);
|
||||||
|
|
||||||
// Usage.
|
// Usage.
|
||||||
void print_usage(char** argv) {
|
static void print_usage(char** argv) {
|
||||||
LOG("USAGE: %s [-f] [-j n | -J s] [-hv]", argv[0]);
|
LOG("USAGE: %s [-f] [-j n | -J s] [-hv]", argv[0]);
|
||||||
LOG("Options are:");
|
LOG("Options are:");
|
||||||
LOG("\t-f - Fullscreen");
|
LOG("\t-f - Fullscreen");
|
||||||
@ -120,6 +124,12 @@ int main(int argc, char** argv) {
|
|||||||
joystick_use(indjoystick);
|
joystick_use(indjoystick);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Misc.
|
||||||
|
if(ai_init())
|
||||||
|
WARN("Error initializing AI");
|
||||||
|
|
||||||
|
gl_fontInit(&fdefault, "/usr/share/fonts/truetype/freefont/FreeSans.ttf", 16);
|
||||||
|
|
||||||
// Data loading.
|
// Data loading.
|
||||||
ships_load();
|
ships_load();
|
||||||
|
|
||||||
@ -144,9 +154,13 @@ int main(int argc, char** argv) {
|
|||||||
update_all();
|
update_all();
|
||||||
}
|
}
|
||||||
space_exit();
|
space_exit();
|
||||||
|
|
||||||
// Unload data.
|
// Unload data.
|
||||||
pilots_free();
|
pilots_free();
|
||||||
ships_free();
|
ships_free();
|
||||||
|
|
||||||
|
gl_freeFont(&fdefault);
|
||||||
|
|
||||||
// Exit subsystems.
|
// Exit subsystems.
|
||||||
joystick_exit();
|
joystick_exit();
|
||||||
gl_exit(); // Kills video output.
|
gl_exit(); // Kills video output.
|
||||||
@ -165,6 +179,22 @@ static void update_all(void) {
|
|||||||
space_render(dt);
|
space_render(dt);
|
||||||
pilots_update(dt);
|
pilots_update(dt);
|
||||||
|
|
||||||
|
display_fps(dt);
|
||||||
|
|
||||||
SDL_GL_SwapBuffers();
|
SDL_GL_SwapBuffers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static double fps = 0.;
|
||||||
|
static double fps_cur = 0.;
|
||||||
|
static double fps_dt = 1.;
|
||||||
|
static void display_fps(const double dt) {
|
||||||
|
fps_dt += dt;
|
||||||
|
fps_cur += 1.;
|
||||||
|
if(fps_dt > 1.) {
|
||||||
|
fps = fps_cur;
|
||||||
|
fps_dt = fps_cur = 0.;
|
||||||
|
}
|
||||||
|
Vec2 pos = { .x = 10., .y = (double)(gl_screen.h-20) };
|
||||||
|
gl_print(&fdefault, &pos, "%3.2f", fps);
|
||||||
|
}
|
||||||
|
|
||||||
|
254
src/opengl.c
254
src/opengl.c
@ -1,6 +1,12 @@
|
|||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
#include <SDL_image.h>
|
#include <SDL_image.h>
|
||||||
|
#include <ft2build.h>
|
||||||
|
#include <freetype/freetype.h>
|
||||||
|
#include <freetype/ftglyph.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "def.h"
|
#include "def.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "opengl.h"
|
#include "opengl.h"
|
||||||
@ -14,7 +20,25 @@ gl_info gl_screen;
|
|||||||
// Our precious camera.
|
// Our precious camera.
|
||||||
Vec2* gl_camera;
|
Vec2* gl_camera;
|
||||||
|
|
||||||
|
// Misc.
|
||||||
static int flip_surface(SDL_Surface* surface);
|
static int flip_surface(SDL_Surface* surface);
|
||||||
|
static int pot(int n);
|
||||||
|
// gl_texture.
|
||||||
|
static GLuint gl_loadSurface(SDL_Surface* surface, int* rw, int* rh);
|
||||||
|
// Gl font.
|
||||||
|
static void gl_fontMakeDList(FT_Face face, char ch, GLuint list_base, GLuint* tex_base);
|
||||||
|
|
||||||
|
// ================
|
||||||
|
// MISC!
|
||||||
|
// ================
|
||||||
|
|
||||||
|
// Get me the closest power of two plox.
|
||||||
|
static int pot(int n) {
|
||||||
|
int i = 1;
|
||||||
|
while( i < n)
|
||||||
|
i<<=1;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
// Flips the surface vertically. Return 0 on success.
|
// Flips the surface vertically. Return 0 on success.
|
||||||
static int flip_surface(SDL_Surface* surface) {
|
static int flip_surface(SDL_Surface* surface) {
|
||||||
@ -42,38 +66,22 @@ static int flip_surface(SDL_Surface* surface) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load the SDL_Surface to an opengl texture.
|
// ================
|
||||||
gl_texture* gl_loadImage(SDL_Surface* surface) {
|
// TEXTURE!
|
||||||
|
// ================
|
||||||
|
|
||||||
|
// Returns the texture ID.
|
||||||
|
// Stores real sizes in rw/rh (from POT padding).
|
||||||
|
static GLuint gl_loadSurface(SDL_Surface* surface, int* rw, int* rh) {
|
||||||
|
GLuint texture;
|
||||||
SDL_Surface* tmp;
|
SDL_Surface* tmp;
|
||||||
Uint32 saved_flags;
|
Uint32 saved_flags;
|
||||||
Uint8 saved_alpha;
|
Uint8 saved_alpha;
|
||||||
int potw, poth;
|
|
||||||
|
|
||||||
// Set up the texture defaults.
|
|
||||||
gl_texture* texture = MALLOC_L(gl_texture);
|
|
||||||
texture->w = (FP)surface->w;
|
|
||||||
texture->h = (FP)surface->h;
|
|
||||||
texture->sx = 1.;
|
|
||||||
texture->sy = 1.;
|
|
||||||
|
|
||||||
// Ensure size is power of two.
|
|
||||||
potw = surface->w;
|
|
||||||
if((potw &(potw-1)) != 0) {
|
|
||||||
potw = 1;
|
|
||||||
while(potw < surface->w)
|
|
||||||
potw <<= 1;
|
|
||||||
}
|
|
||||||
texture->rw = potw;
|
|
||||||
|
|
||||||
poth = surface->h;
|
if(rw)*rw = pot(surface->w);
|
||||||
if((poth &(poth-1)) != 0) {
|
if(rh)*rh = pot(surface->h);
|
||||||
poth = 1;
|
|
||||||
while(poth < surface->h)
|
|
||||||
poth <<= 1;
|
|
||||||
}
|
|
||||||
texture->rh = poth;
|
|
||||||
|
|
||||||
if(surface->w != potw || surface->h != poth) {
|
if(surface->w != *rw || surface->h != *rh) {
|
||||||
// Size isn't original.
|
// Size isn't original.
|
||||||
SDL_Rect rtemp;
|
SDL_Rect rtemp;
|
||||||
rtemp.x = rtemp.y = 0;
|
rtemp.x = rtemp.y = 0;
|
||||||
@ -88,14 +96,14 @@ gl_texture* gl_loadImage(SDL_Surface* surface) {
|
|||||||
|
|
||||||
// Create the temp POT surface.
|
// Create the temp POT surface.
|
||||||
tmp = SDL_CreateRGBSurface(SDL_SRCCOLORKEY,
|
tmp = SDL_CreateRGBSurface(SDL_SRCCOLORKEY,
|
||||||
texture->rw, texture->rh, surface->format->BytesPerPixel*8, RGBMASK);
|
*rw, *rh, surface->format->BytesPerPixel*8, RGBMASK);
|
||||||
if(tmp == NULL) {
|
if(tmp == NULL) {
|
||||||
WARN("Unable to create POT surface %s", SDL_GetError());
|
WARN("Unable to create POT surface %s", SDL_GetError());
|
||||||
return NULL;
|
return 0;
|
||||||
}
|
}
|
||||||
if(SDL_FillRect(tmp, NULL, SDL_MapRGBA(surface->format, 0, 0, 0, SDL_ALPHA_TRANSPARENT))) {
|
if(SDL_FillRect(tmp, NULL, SDL_MapRGBA(surface->format, 0, 0, 0, SDL_ALPHA_TRANSPARENT))) {
|
||||||
WARN("Unable to fill rect: %s", SDL_GetError());
|
WARN("Unable to fill rect: %s", SDL_GetError());
|
||||||
return NULL;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_BlitSurface(surface, &rtemp, tmp, &rtemp);
|
SDL_BlitSurface(surface, &rtemp, tmp, &rtemp);
|
||||||
@ -109,14 +117,14 @@ gl_texture* gl_loadImage(SDL_Surface* surface) {
|
|||||||
|
|
||||||
// Create the temp POT surface.
|
// Create the temp POT surface.
|
||||||
tmp = SDL_CreateRGBSurface(SDL_SRCCOLORKEY,
|
tmp = SDL_CreateRGBSurface(SDL_SRCCOLORKEY,
|
||||||
texture->rw, texture->rh, surface->format->BytesPerPixel*8, RGBMASK);
|
*rw, *rh, surface->format->BytesPerPixel*8, RGBMASK);
|
||||||
if(tmp == NULL) {
|
if(tmp == NULL) {
|
||||||
WARN("Unable to create POT surface %s", SDL_GetError());
|
WARN("Unable to create POT surface %s", SDL_GetError());
|
||||||
return NULL;
|
return 0;
|
||||||
}
|
}
|
||||||
if(SDL_FillRect(tmp, NULL, SDL_MapRGBA(surface->format, 0, 0, 0, SDL_ALPHA_TRANSPARENT))) {
|
if(SDL_FillRect(tmp, NULL, SDL_MapRGBA(surface->format, 0, 0, 0, SDL_ALPHA_TRANSPARENT))) {
|
||||||
WARN("Unable to fill rect: %s", SDL_GetError());
|
WARN("Unable to fill rect: %s", SDL_GetError());
|
||||||
return NULL;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_BlitSurface(surface, &rtemp, tmp, &rtemp);
|
SDL_BlitSurface(surface, &rtemp, tmp, &rtemp);
|
||||||
@ -129,8 +137,8 @@ gl_texture* gl_loadImage(SDL_Surface* surface) {
|
|||||||
SDL_SetAlpha(surface, saved_flags, saved_alpha);
|
SDL_SetAlpha(surface, saved_flags, saved_alpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
glGenTextures(1, &texture->texture); // Create the texure.
|
glGenTextures(1, &texture); // Create the texure.
|
||||||
glBindTexture(GL_TEXTURE_2D, texture->texture); // Load the texture.
|
glBindTexture(GL_TEXTURE_2D, texture); // Load the texture.
|
||||||
|
|
||||||
// Filtering, LINEAR is better for scaling, nearest looks nicer, LINEAR
|
// Filtering, LINEAR is better for scaling, nearest looks nicer, LINEAR
|
||||||
// also seems to create a bit of artifacts around the edges.
|
// also seems to create a bit of artifacts around the edges.
|
||||||
@ -144,8 +152,24 @@ gl_texture* gl_loadImage(SDL_Surface* surface) {
|
|||||||
SDL_UnlockSurface(surface);
|
SDL_UnlockSurface(surface);
|
||||||
SDL_FreeSurface(surface);
|
SDL_FreeSurface(surface);
|
||||||
|
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load the SDL_Surface to an openGL texture.
|
||||||
|
gl_texture* gl_loadImage(SDL_Surface* surface) {
|
||||||
|
int rw, rh;
|
||||||
|
|
||||||
|
// Set up the texture defaults.
|
||||||
|
gl_texture* texture = MALLOC_L(gl_texture);
|
||||||
|
texture->w = (FP)surface->w;
|
||||||
|
texture->h = (FP)surface->h;
|
||||||
texture->sx = 1.;
|
texture->sx = 1.;
|
||||||
texture->sy = 1.;
|
texture->sy = 1.;
|
||||||
|
|
||||||
|
texture->texture = gl_loadSurface(surface, &rw, &rh);
|
||||||
|
|
||||||
|
texture->rw = (FP)rw;
|
||||||
|
texture->rh = (FP)rh;
|
||||||
texture->sw = texture->w;
|
texture->sw = texture->w;
|
||||||
texture->sh = texture->h;
|
texture->sh = texture->h;
|
||||||
|
|
||||||
@ -190,13 +214,17 @@ gl_texture* gl_newSprite(const char* path, const int sx, const int sy) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Free the texture.
|
// Free the texture.
|
||||||
void gl_free(gl_texture* texture) {
|
void gl_freeTexture(gl_texture* texture) {
|
||||||
glDeleteTextures(1, &texture->texture);
|
glDeleteTextures(1, &texture->texture);
|
||||||
free(texture);
|
free(texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ================
|
||||||
|
// BLITTING!
|
||||||
|
// ================
|
||||||
|
|
||||||
// Blit the sprite at given position.
|
// Blit the sprite at given position.
|
||||||
void gl_blitSprite(gl_texture* sprite, Vec2* pos, const int sx, const int sy) {
|
void gl_blitSprite(const gl_texture* sprite, const Vec2* pos, const int sx, const int sy) {
|
||||||
// Don't bother drawing if offscreen -- waste of cycles.
|
// Don't bother drawing if offscreen -- waste of cycles.
|
||||||
if(fabs(pos->x - gl_camera->x) > gl_screen.w / 2 + sprite->sw / 2 ||
|
if(fabs(pos->x - gl_camera->x) > gl_screen.w / 2 + sprite->sw / 2 ||
|
||||||
fabs(pos->y-gl_camera->y) > gl_screen.h / 2 + sprite->sh / 2)
|
fabs(pos->y-gl_camera->y) > gl_screen.h / 2 + sprite->sh / 2)
|
||||||
@ -232,7 +260,7 @@ void gl_blitSprite(gl_texture* sprite, Vec2* pos, const int sx, const int sy) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Just straight out blit the thing at position.
|
// Just straight out blit the thing at position.
|
||||||
void gl_blitStatic(gl_texture* texture, Vec2* pos) {
|
void gl_blitStatic(const gl_texture* texture, const Vec2* pos) {
|
||||||
glMatrixMode(GL_PROJECTION);
|
glMatrixMode(GL_PROJECTION);
|
||||||
glPushMatrix(); // Set up translation matrix.
|
glPushMatrix(); // Set up translation matrix.
|
||||||
glTranslatef(pos->x - (FP)gl_screen.w/2., pos->y - (FP)gl_screen.h/2., 0);
|
glTranslatef(pos->x - (FP)gl_screen.w/2., pos->y - (FP)gl_screen.h/2., 0);
|
||||||
@ -255,10 +283,156 @@ void gl_blitStatic(gl_texture* texture, Vec2* pos) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Bind our precious camera to a vector.
|
// Bind our precious camera to a vector.
|
||||||
void gl_bindCamera(Vec2* pos) {
|
void gl_bindCamera(const Vec2* pos) {
|
||||||
gl_camera = pos;
|
gl_camera = (Vec2*)pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Print text on screen! YES!!!! Just like printf! But different!
|
||||||
|
void gl_print(const gl_font* ft_font, Vec2* pos, const char* fmt, ...) {
|
||||||
|
//float h = ft_font->h / .63; // Slightly increases font size.
|
||||||
|
char text[256];
|
||||||
|
va_list ap;
|
||||||
|
//int i;
|
||||||
|
|
||||||
|
if(fmt == NULL)
|
||||||
|
*text = 0;
|
||||||
|
else {
|
||||||
|
// convert the symbols to text.
|
||||||
|
va_start(ap, fmt);
|
||||||
|
vsprintf(text, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
glListBase(ft_font->list_base);
|
||||||
|
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
//for(i = 0; i < strlen(text); i++) {
|
||||||
|
glPushMatrix();
|
||||||
|
glTranslatef(pos->x - (FP)gl_screen.w/2., pos->y - (FP)gl_screen.h/2., 0);
|
||||||
|
glCallLists(strlen(text), GL_UNSIGNED_BYTE, &text);
|
||||||
|
glPopMatrix();
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ================
|
||||||
|
// FONT!
|
||||||
|
// ================
|
||||||
|
static void gl_fontMakeDList(FT_Face face, char ch, GLuint list_base, GLuint* tex_base) {
|
||||||
|
FT_Glyph glyph;
|
||||||
|
FT_Bitmap bitmap;
|
||||||
|
GLubyte* expanded_data;
|
||||||
|
int w, h;
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
if(FT_Load_Glyph(face, FT_Get_Char_Index(face, ch), FT_LOAD_DEFAULT))
|
||||||
|
WARN("FT_Load_Glyph failed");
|
||||||
|
|
||||||
|
if(FT_Get_Glyph(face->glyph, &glyph))
|
||||||
|
WARN("FT_Ge_Glyph failed");
|
||||||
|
|
||||||
|
// Convert your glyph to a bitmap.
|
||||||
|
FT_Glyph_To_Bitmap(&glyph, ft_render_mode_normal, 0, 1);
|
||||||
|
FT_BitmapGlyph bitmap_glyph = (FT_BitmapGlyph)glyph;
|
||||||
|
|
||||||
|
bitmap = bitmap_glyph->bitmap; // To simplify.
|
||||||
|
|
||||||
|
// Need the POT wrapping for GL.
|
||||||
|
w = pot(bitmap.width);
|
||||||
|
h = pot(bitmap.rows);
|
||||||
|
|
||||||
|
// Memory for textured data.
|
||||||
|
// Bitmap is useing two channels, one for luminosity and one for alpha.
|
||||||
|
expanded_data = (GLubyte*)malloc(sizeof(GLubyte)*2*w*h);
|
||||||
|
for(j = 0; j < h; j++) {
|
||||||
|
for(i = 0; i < w; i++) {
|
||||||
|
expanded_data[2*(i+j*w)] = expanded_data[2*(i+j*w)+1] =
|
||||||
|
(i >= bitmap.width || j >= bitmap.rows) ? 0 : bitmap.buffer[i + bitmap.width*j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Create the GL texture.
|
||||||
|
glBindTexture(GL_TEXTURE_2D, tex_base[(int)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, w, h, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, expanded_data);
|
||||||
|
|
||||||
|
free(expanded_data); // No need for this now.
|
||||||
|
|
||||||
|
// Create the display lists.
|
||||||
|
glNewList(list_base+ch, GL_COMPILE);
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, tex_base[(int)ch]);
|
||||||
|
|
||||||
|
glPushMatrix();
|
||||||
|
|
||||||
|
// Corrects a spacing flaw between letters.
|
||||||
|
glTranslatef(bitmap_glyph->left, 0,0);
|
||||||
|
|
||||||
|
// Downwards correction for letters like g or y.
|
||||||
|
glTranslatef(0, bitmap_glyph->top-bitmap.rows,0);
|
||||||
|
|
||||||
|
// Take the opengl POT wrapping into account.
|
||||||
|
FP x = (FP)bitmap.width/(FP)w;
|
||||||
|
FP y = (FP)bitmap.rows/(FP)h;
|
||||||
|
|
||||||
|
// Draw the texture mapped quad.
|
||||||
|
glBegin(GL_QUADS);
|
||||||
|
glTexCoord2d(0, 0);
|
||||||
|
glVertex2f(0, bitmap.rows);
|
||||||
|
glTexCoord2d(x, y);
|
||||||
|
glVertex2f(bitmap.width, 0);
|
||||||
|
glTexCoord2d(x, 0);
|
||||||
|
glVertex2f(bitmap.width, bitmap.rows);
|
||||||
|
glEnd();
|
||||||
|
|
||||||
|
glPopMatrix();
|
||||||
|
glTranslatef(face->glyph->advance.x >> 6, 0,0);
|
||||||
|
|
||||||
|
// End of the display list.
|
||||||
|
glEndList();
|
||||||
|
}
|
||||||
|
|
||||||
|
void gl_fontInit(gl_font* font, const char* fname, unsigned int h) {
|
||||||
|
font->textures = malloc(sizeof(GLuint)*128);
|
||||||
|
font->h = h;
|
||||||
|
|
||||||
|
// Create a FreeType font library.
|
||||||
|
FT_Library library;
|
||||||
|
if(FT_Init_FreeType(&library)) {
|
||||||
|
WARN("FT_Init_FreeType failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Objects that freetype uses to store font info.
|
||||||
|
FT_Face face;
|
||||||
|
if(FT_New_Face(library, fname, 0, &face))
|
||||||
|
WARN("FT_New_Face failed loading library from %s", fname);
|
||||||
|
|
||||||
|
// FreeType is pretty nice and measures using 1/64 of a pixel, therfore expand.
|
||||||
|
FT_Set_Char_Size(face, h << 6, h << 6, 96, 96);
|
||||||
|
|
||||||
|
// Have OpenGL allocate space for the textures / display lists.
|
||||||
|
font->list_base = glGenLists(128);
|
||||||
|
glGenTextures(128, font->textures);
|
||||||
|
|
||||||
|
// Create each of the font display lists.
|
||||||
|
unsigned char i;
|
||||||
|
for(i = 0; i < 128; i++)
|
||||||
|
gl_fontMakeDList(face, i, font->list_base, font->textures);
|
||||||
|
|
||||||
|
// We can now free the face and library.
|
||||||
|
FT_Done_Face(face);
|
||||||
|
FT_Done_FreeType(library);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gl_freeFont(gl_font* font) {
|
||||||
|
glDeleteLists(font->list_base, 128);
|
||||||
|
glDeleteTextures(128, font->textures);
|
||||||
|
free(font->textures);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ================
|
||||||
|
// GLOBAL.
|
||||||
|
// ================
|
||||||
|
|
||||||
// Initialize SDL/OpenGL etc.
|
// Initialize SDL/OpenGL etc.
|
||||||
int gl_init(void) {
|
int gl_init(void) {
|
||||||
int depth, i, supported = 0;
|
int depth, i, supported = 0;
|
||||||
|
20
src/opengl.h
20
src/opengl.h
@ -39,16 +39,28 @@ typedef struct {
|
|||||||
GLuint texture; // The opengl texture itself.
|
GLuint texture; // The opengl texture itself.
|
||||||
} gl_texture;
|
} gl_texture;
|
||||||
|
|
||||||
|
// Font info.
|
||||||
|
typedef struct {
|
||||||
|
float h; // Height.
|
||||||
|
GLuint* textures;
|
||||||
|
GLuint list_base;
|
||||||
|
} gl_font;
|
||||||
|
|
||||||
|
// gl_font loading/freeing.
|
||||||
|
void gl_fontInit(gl_font* font, const char* fname, unsigned int h);
|
||||||
|
void gl_freeFont(gl_font* font);
|
||||||
|
|
||||||
// gl_texute loading/freeing.
|
// gl_texute loading/freeing.
|
||||||
gl_texture* gl_loadImage(SDL_Surface* surface); // Frees the surface.
|
gl_texture* gl_loadImage(SDL_Surface* surface); // Frees the surface.
|
||||||
gl_texture* gl_newImage(const char* path);
|
gl_texture* gl_newImage(const char* path);
|
||||||
gl_texture* gl_newSprite(const char* path, const int sx, const int sy);
|
gl_texture* gl_newSprite(const char* path, const int sx, const int sy);
|
||||||
void gl_free(gl_texture* texture);
|
void gl_freeTexture(gl_texture* texture);
|
||||||
|
|
||||||
// Rendering.
|
// Rendering.
|
||||||
void gl_blitSprite(gl_texture* sprite, Vec2* pos, const int sx, const int sy);
|
void gl_blitSprite(const gl_texture* sprite, const Vec2* pos, const int sx, const int sy);
|
||||||
void gl_blitStatic(gl_texture* texture, Vec2* pos);
|
void gl_blitStatic(const gl_texture* texture, const Vec2* pos);
|
||||||
void gl_bindCamera(Vec2* pos);
|
void gl_bindCamera(const Vec2* pos);
|
||||||
|
void gl_print(const gl_font* ft_font, Vec2* pos, const char* fmt, ...);
|
||||||
|
|
||||||
// Initialize/cleanup.
|
// Initialize/cleanup.
|
||||||
int gl_init(void);
|
int gl_init(void);
|
||||||
|
@ -53,7 +53,7 @@ unsigned int pilot_create(Ship* ship, char* name, const Vec2* vel,
|
|||||||
const Vec2* pos, const int flags);
|
const Vec2* pos, const int flags);
|
||||||
|
|
||||||
// Cleanup.
|
// Cleanup.
|
||||||
void pilot_free(void);
|
void pilots_free(void);
|
||||||
|
|
||||||
// Update.
|
// Update.
|
||||||
void pilots_update(FP dt);
|
void pilots_update(FP dt);
|
||||||
|
@ -145,7 +145,7 @@ void ships_free(void) {
|
|||||||
for(i = 0; i < ships; i++) {
|
for(i = 0; i < ships; i++) {
|
||||||
if((ship_stack+i)->name)
|
if((ship_stack+i)->name)
|
||||||
free((ship_stack+i)->name);
|
free((ship_stack+i)->name);
|
||||||
gl_free((ship_stack+i)->gfx_ship);
|
gl_freeTexture((ship_stack+i)->gfx_ship);
|
||||||
}
|
}
|
||||||
free(ship_stack);
|
free(ship_stack);
|
||||||
ship_stack = NULL;
|
ship_stack = NULL;
|
||||||
|
@ -151,6 +151,6 @@ void space_render(FP dt) {
|
|||||||
void space_exit(void) {
|
void space_exit(void) {
|
||||||
int i;
|
int i;
|
||||||
for(i = 0; i < STAR_LAYERS; i++)
|
for(i = 0; i < STAR_LAYERS; i++)
|
||||||
gl_free(starBG[i]);
|
gl_freeTexture(starBG[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user