2007-05-22 15:03:32 +00:00
|
|
|
|
2007-08-22 07:52:33 +00:00
|
|
|
#include <engine/external/glfw/include/GL/glfw.h>
|
|
|
|
#include <engine/external/pnglite/pnglite.h>
|
2007-05-22 15:03:32 +00:00
|
|
|
|
2007-08-22 07:52:33 +00:00
|
|
|
#include <engine/system.h>
|
|
|
|
#include <engine/interface.h>
|
|
|
|
#include <engine/config.h>
|
|
|
|
#include <engine/keys.h>
|
2007-05-27 00:47:07 +00:00
|
|
|
|
|
|
|
#include <string.h>
|
2007-08-04 09:20:59 +00:00
|
|
|
#include <stdio.h>
|
2007-08-22 07:52:33 +00:00
|
|
|
#include <math.h>
|
2007-05-27 00:47:07 +00:00
|
|
|
|
2007-08-22 07:52:33 +00:00
|
|
|
// compressed textures
|
|
|
|
#define GL_COMPRESSED_RGB_ARB 0x84ED
|
|
|
|
#define GL_COMPRESSED_RGBA_ARB 0x84EE
|
2007-05-27 00:47:07 +00:00
|
|
|
|
2007-09-23 18:27:04 +00:00
|
|
|
enum
|
|
|
|
{
|
|
|
|
DRAWING_QUADS=1,
|
|
|
|
DRAWING_LINES=2,
|
|
|
|
};
|
|
|
|
|
2007-08-22 07:52:33 +00:00
|
|
|
//
|
|
|
|
typedef struct { float x, y, z; } VEC3;
|
|
|
|
typedef struct { float u, v; } TEXCOORD;
|
|
|
|
typedef struct { float r, g, b, a; } COLOR;
|
2007-05-22 15:03:32 +00:00
|
|
|
|
2007-08-22 07:52:33 +00:00
|
|
|
typedef struct
|
2007-05-22 15:03:32 +00:00
|
|
|
{
|
2007-08-22 07:52:33 +00:00
|
|
|
VEC3 pos;
|
|
|
|
TEXCOORD tex;
|
|
|
|
COLOR color;
|
|
|
|
} VERTEX;
|
2007-05-22 15:03:32 +00:00
|
|
|
|
2007-07-29 15:21:25 +00:00
|
|
|
const int vertex_buffer_size = 32*1024;
|
2007-08-22 07:52:33 +00:00
|
|
|
static VERTEX *vertices = 0;
|
2007-07-24 22:53:43 +00:00
|
|
|
static int num_vertices = 0;
|
2007-08-22 07:52:33 +00:00
|
|
|
|
|
|
|
static COLOR color[4];
|
|
|
|
static TEXCOORD texture[4];
|
2007-05-22 15:03:32 +00:00
|
|
|
|
2007-08-04 09:20:59 +00:00
|
|
|
static int do_screenshot = 0;
|
|
|
|
|
|
|
|
static int screen_width = -1;
|
|
|
|
static int screen_height = -1;
|
2007-05-22 15:03:32 +00:00
|
|
|
static float rotation = 0;
|
2007-09-23 18:27:04 +00:00
|
|
|
static int drawing = 0;
|
2007-07-24 22:53:43 +00:00
|
|
|
|
2007-07-22 12:01:20 +00:00
|
|
|
static float screen_x0 = 0;
|
|
|
|
static float screen_y0 = 0;
|
|
|
|
static float screen_x1 = 0;
|
|
|
|
static float screen_y1 = 0;
|
2007-05-22 15:03:32 +00:00
|
|
|
|
2007-08-22 07:52:33 +00:00
|
|
|
typedef struct
|
2007-05-22 15:03:32 +00:00
|
|
|
{
|
2007-08-22 07:52:33 +00:00
|
|
|
GLuint tex;
|
2007-07-30 19:46:31 +00:00
|
|
|
int memsize;
|
2007-05-22 15:03:32 +00:00
|
|
|
int flags;
|
|
|
|
int next;
|
2007-08-22 07:52:33 +00:00
|
|
|
} TEXTURE;
|
2007-05-22 15:03:32 +00:00
|
|
|
|
|
|
|
|
2007-08-22 07:52:33 +00:00
|
|
|
enum
|
|
|
|
{
|
|
|
|
MAX_TEXTURES = 128
|
|
|
|
};
|
|
|
|
|
|
|
|
static TEXTURE textures[MAX_TEXTURES];
|
2007-05-22 15:03:32 +00:00
|
|
|
static int first_free_texture;
|
2007-07-30 19:46:31 +00:00
|
|
|
static int memory_usage = 0;
|
2007-05-22 15:03:32 +00:00
|
|
|
|
2007-07-13 21:22:45 +00:00
|
|
|
static const unsigned char null_texture_data[] = {
|
2007-05-22 15:03:32 +00:00
|
|
|
0xff,0x00,0x00,0xff, 0xff,0x00,0x00,0xff, 0x00,0xff,0x00,0xff, 0x00,0xff,0x00,0xff,
|
|
|
|
0xff,0x00,0x00,0xff, 0xff,0x00,0x00,0xff, 0x00,0xff,0x00,0xff, 0x00,0xff,0x00,0xff,
|
|
|
|
0x00,0x00,0xff,0xff, 0x00,0x00,0xff,0xff, 0xff,0xff,0x00,0xff, 0xff,0xff,0x00,0xff,
|
|
|
|
0x00,0x00,0xff,0xff, 0x00,0x00,0xff,0xff, 0xff,0xff,0x00,0xff, 0xff,0xff,0x00,0xff,
|
|
|
|
};
|
|
|
|
|
2007-09-23 18:27:04 +00:00
|
|
|
static void flush()
|
2007-05-22 15:03:32 +00:00
|
|
|
{
|
2007-09-23 18:27:04 +00:00
|
|
|
if(num_vertices == 0)
|
|
|
|
return;
|
2007-07-24 22:53:43 +00:00
|
|
|
|
2007-09-23 18:27:04 +00:00
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
|
|
|
|
|
|
glVertexPointer(3, GL_FLOAT,
|
|
|
|
sizeof(VERTEX),
|
|
|
|
(char*)vertices);
|
|
|
|
glTexCoordPointer(2, GL_FLOAT,
|
|
|
|
sizeof(VERTEX),
|
|
|
|
(char*)vertices + sizeof(float)*3);
|
|
|
|
glColorPointer(4, GL_FLOAT,
|
|
|
|
sizeof(VERTEX),
|
|
|
|
(char*)vertices + sizeof(float)*5);
|
|
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
|
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
|
|
glEnableClientState(GL_COLOR_ARRAY);
|
|
|
|
|
|
|
|
if(drawing == DRAWING_QUADS)
|
|
|
|
glDrawArrays(GL_QUADS, 0, num_vertices);
|
|
|
|
else if(drawing == DRAWING_LINES)
|
|
|
|
glDrawArrays(GL_LINES, 0, num_vertices);
|
|
|
|
|
|
|
|
// Reset pointer
|
|
|
|
num_vertices = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void draw_line()
|
|
|
|
{
|
|
|
|
num_vertices += 2;
|
|
|
|
if((num_vertices + 2) >= vertex_buffer_size)
|
|
|
|
flush();
|
|
|
|
}
|
|
|
|
|
|
|
|
static void draw_quad()
|
|
|
|
{
|
|
|
|
num_vertices += 4;
|
|
|
|
if((num_vertices + 4) >= vertex_buffer_size)
|
|
|
|
flush();
|
2007-07-24 22:53:43 +00:00
|
|
|
}
|
2007-07-29 13:21:33 +00:00
|
|
|
|
2007-08-22 07:52:33 +00:00
|
|
|
int gfx_init()
|
2007-05-22 15:03:32 +00:00
|
|
|
{
|
2007-08-04 09:20:59 +00:00
|
|
|
screen_width = config.gfx_screen_width;
|
|
|
|
screen_height = config.gfx_screen_height;
|
2007-08-07 18:03:36 +00:00
|
|
|
|
2007-08-22 07:52:33 +00:00
|
|
|
glfwInit();
|
|
|
|
|
2007-08-14 18:37:16 +00:00
|
|
|
if(config.stress)
|
|
|
|
{
|
|
|
|
screen_width = 320;
|
|
|
|
screen_height = 240;
|
|
|
|
}
|
|
|
|
|
2007-08-07 18:03:36 +00:00
|
|
|
if(config.gfx_fullscreen)
|
|
|
|
{
|
2007-08-22 07:52:33 +00:00
|
|
|
int result = glfwOpenWindow(screen_width, screen_height, 8, 8, 8, 0, 0, 0, GLFW_FULLSCREEN);
|
|
|
|
if(result != GL_TRUE)
|
2007-08-07 18:03:36 +00:00
|
|
|
{
|
|
|
|
dbg_msg("game", "failed to create gl context");
|
2007-08-22 07:52:33 +00:00
|
|
|
return 0;
|
2007-08-07 18:03:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2007-05-22 15:03:32 +00:00
|
|
|
{
|
2007-08-22 07:52:33 +00:00
|
|
|
int result = glfwOpenWindow(screen_width, screen_height, 0, 0, 0, 0, 0, 0, GLFW_WINDOW);
|
|
|
|
if(result != GL_TRUE)
|
2007-08-07 18:03:36 +00:00
|
|
|
{
|
|
|
|
dbg_msg("game", "failed to create gl context");
|
2007-08-22 07:52:33 +00:00
|
|
|
return 0;
|
2007-08-07 18:03:36 +00:00
|
|
|
}
|
2007-05-22 15:03:32 +00:00
|
|
|
}
|
2007-08-14 18:37:16 +00:00
|
|
|
|
2007-08-22 07:52:33 +00:00
|
|
|
glfwSetWindowTitle("Teewars");
|
2007-08-14 18:37:16 +00:00
|
|
|
|
|
|
|
// We don't want to see the window when we run the stress testing
|
|
|
|
if(config.stress)
|
2007-08-22 07:52:33 +00:00
|
|
|
glfwIconifyWindow();
|
2007-07-22 13:42:28 +00:00
|
|
|
|
2007-05-22 15:03:32 +00:00
|
|
|
// Init vertices
|
2007-07-24 22:53:43 +00:00
|
|
|
if (vertices)
|
|
|
|
mem_free(vertices);
|
2007-08-22 07:52:33 +00:00
|
|
|
vertices = (VERTEX*)mem_alloc(sizeof(VERTEX) * vertex_buffer_size, 1);
|
2007-07-24 22:53:43 +00:00
|
|
|
num_vertices = 0;
|
2007-05-22 15:03:32 +00:00
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
dbg_msg("gfx", "OpenGL version %d.%d.%d", context.version_major(),
|
|
|
|
context.version_minor(),
|
|
|
|
context.version_rev());*/
|
|
|
|
|
2007-07-29 15:55:04 +00:00
|
|
|
gfx_mapscreen(0,0,config.gfx_screen_width, config.gfx_screen_height);
|
2007-05-22 15:03:32 +00:00
|
|
|
|
|
|
|
// TODO: make wrappers for this
|
|
|
|
glEnable(GL_BLEND);
|
|
|
|
|
|
|
|
// model
|
2007-08-22 07:52:33 +00:00
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glLoadIdentity();
|
2007-05-22 15:03:32 +00:00
|
|
|
|
|
|
|
// Set all z to -5.0f
|
2007-08-22 07:52:33 +00:00
|
|
|
int i;
|
|
|
|
for (i = 0; i < vertex_buffer_size; i++)
|
2007-07-24 22:53:43 +00:00
|
|
|
vertices[i].pos.z = -5.0f;
|
2007-05-22 15:03:32 +00:00
|
|
|
|
|
|
|
// init textures
|
|
|
|
first_free_texture = 0;
|
2007-08-22 07:52:33 +00:00
|
|
|
for(i = 0; i < MAX_TEXTURES; i++)
|
2007-05-22 15:03:32 +00:00
|
|
|
textures[i].next = i+1;
|
|
|
|
textures[MAX_TEXTURES-1].next = -1;
|
|
|
|
|
2007-07-29 22:09:15 +00:00
|
|
|
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
2007-07-30 19:46:31 +00:00
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
2007-08-22 07:52:33 +00:00
|
|
|
|
|
|
|
// init input
|
|
|
|
inp_init();
|
2007-07-26 19:09:31 +00:00
|
|
|
|
2007-05-22 15:03:32 +00:00
|
|
|
// create null texture, will get id=0
|
2007-05-27 00:47:07 +00:00
|
|
|
gfx_load_texture_raw(4,4,IMG_RGBA,null_texture_data);
|
2007-07-22 11:46:25 +00:00
|
|
|
|
2007-07-22 13:42:28 +00:00
|
|
|
// set vsync as needed
|
2007-07-29 15:55:04 +00:00
|
|
|
gfx_set_vsync(config.gfx_vsync);
|
2007-07-22 13:42:28 +00:00
|
|
|
|
2007-08-22 07:52:33 +00:00
|
|
|
return 1;
|
2007-05-22 15:03:32 +00:00
|
|
|
}
|
|
|
|
|
2007-08-04 09:20:59 +00:00
|
|
|
|
2007-08-07 18:28:51 +00:00
|
|
|
int gfx_window_active()
|
|
|
|
{
|
2007-08-22 07:52:33 +00:00
|
|
|
return glfwGetWindowParam(GLFW_ACTIVE) == GL_TRUE ? 1 : 0;
|
2007-08-07 18:28:51 +00:00
|
|
|
}
|
|
|
|
|
2007-08-04 09:20:59 +00:00
|
|
|
|
2007-08-22 07:52:33 +00:00
|
|
|
VIDEO_MODE fakemodes[] = {
|
2007-07-26 19:09:31 +00:00
|
|
|
{320,240,8,8,8}, {400,300,8,8,8}, {640,480,8,8,8},
|
|
|
|
{720,400,8,8,8}, {768,576,8,8,8}, {800,600,8,8,8},
|
|
|
|
{1024,600,8,8,8}, {1024,768,8,8,8}, {1152,864,8,8,8},
|
|
|
|
{1280,768,8,8,8}, {1280,800,8,8,8}, {1280,960,8,8,8},
|
|
|
|
{1280,1024,8,8,8}, {1368,768,8,8,8}, {1400,1050,8,8,8},
|
|
|
|
{1440,900,8,8,8}, {1440,1050,8,8,8}, {1600,1000,8,8,8},
|
|
|
|
{1600,1200,8,8,8}, {1680,1050,8,8,8}, {1792,1344,8,8,8},
|
|
|
|
{1800,1440,8,8,8}, {1856,1392,8,8,8}, {1920,1080,8,8,8},
|
|
|
|
{1920,1200,8,8,8}, {1920,1440,8,8,8}, {1920,2400,8,8,8},
|
|
|
|
{2048,1536,8,8,8},
|
|
|
|
|
|
|
|
{320,240,5,6,5}, {400,300,5,6,5}, {640,480,5,6,5},
|
|
|
|
{720,400,5,6,5}, {768,576,5,6,5}, {800,600,5,6,5},
|
|
|
|
{1024,600,5,6,5}, {1024,768,5,6,5}, {1152,864,5,6,5},
|
|
|
|
{1280,768,5,6,5}, {1280,800,5,6,5}, {1280,960,5,6,5},
|
|
|
|
{1280,1024,5,6,5}, {1368,768,5,6,5}, {1400,1050,5,6,5},
|
|
|
|
{1440,900,5,6,5}, {1440,1050,5,6,5}, {1600,1000,5,6,5},
|
|
|
|
{1600,1200,5,6,5}, {1680,1050,5,6,5}, {1792,1344,5,6,5},
|
|
|
|
{1800,1440,5,6,5}, {1856,1392,5,6,5}, {1920,1080,5,6,5},
|
|
|
|
{1920,1200,5,6,5}, {1920,1440,5,6,5}, {1920,2400,5,6,5},
|
|
|
|
{2048,1536,5,6,5}
|
|
|
|
};
|
|
|
|
|
2007-08-22 07:52:33 +00:00
|
|
|
int gfx_get_video_modes(VIDEO_MODE *list, int maxcount)
|
2007-07-21 12:57:36 +00:00
|
|
|
{
|
2007-07-29 15:55:04 +00:00
|
|
|
if(config.gfx_display_all_modes)
|
2007-07-26 19:09:31 +00:00
|
|
|
{
|
|
|
|
mem_copy(list, fakemodes, sizeof(fakemodes));
|
2007-08-22 07:52:33 +00:00
|
|
|
int count = sizeof(fakemodes)/sizeof(VIDEO_MODE);
|
|
|
|
if(maxcount < count)
|
|
|
|
count = maxcount;
|
|
|
|
return count;
|
2007-07-26 19:09:31 +00:00
|
|
|
}
|
2007-08-14 18:37:16 +00:00
|
|
|
|
2007-08-22 07:52:33 +00:00
|
|
|
return glfwGetVideoModes((GLFWvidmode *)list, maxcount);
|
2007-07-21 12:57:36 +00:00
|
|
|
}
|
|
|
|
|
2007-07-22 13:42:28 +00:00
|
|
|
void gfx_set_vsync(int val)
|
|
|
|
{
|
2007-08-22 07:52:33 +00:00
|
|
|
glfwSwapInterval(val);
|
2007-07-22 13:42:28 +00:00
|
|
|
}
|
|
|
|
|
2007-05-22 15:03:32 +00:00
|
|
|
int gfx_unload_texture(int index)
|
|
|
|
{
|
2007-08-22 07:52:33 +00:00
|
|
|
glDeleteTextures(1, &textures[index].tex);
|
2007-05-22 15:03:32 +00:00
|
|
|
textures[index].next = first_free_texture;
|
2007-07-30 19:46:31 +00:00
|
|
|
memory_usage -= textures[index].memsize;
|
2007-05-22 15:03:32 +00:00
|
|
|
first_free_texture = index;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void gfx_blend_normal()
|
|
|
|
{
|
|
|
|
// TODO: wrapper for this
|
|
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
}
|
|
|
|
|
|
|
|
void gfx_blend_additive()
|
|
|
|
{
|
|
|
|
// TODO: wrapper for this
|
|
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
|
|
|
}
|
|
|
|
|
2007-07-30 19:46:31 +00:00
|
|
|
int gfx_memory_usage() { return memory_usage; }
|
|
|
|
|
2007-07-29 15:38:20 +00:00
|
|
|
static unsigned char sample(int w, int h, const unsigned char *data, int u, int v, int offset)
|
|
|
|
{
|
|
|
|
return (data[(v*w+u)*4+offset]+
|
|
|
|
data[(v*w+u+1)*4+offset]+
|
|
|
|
data[((v+1)*w+u)*4+offset]+
|
|
|
|
data[((v+1)*w+u+1)*4+offset])/4;
|
|
|
|
}
|
|
|
|
|
2007-05-27 00:47:07 +00:00
|
|
|
int gfx_load_texture_raw(int w, int h, int format, const void *data)
|
2007-05-22 15:03:32 +00:00
|
|
|
{
|
2007-08-22 07:52:33 +00:00
|
|
|
int mipmap = 1;
|
2007-07-30 19:46:31 +00:00
|
|
|
|
2007-05-22 15:03:32 +00:00
|
|
|
// grab texture
|
|
|
|
int tex = first_free_texture;
|
|
|
|
first_free_texture = textures[tex].next;
|
|
|
|
textures[tex].next = -1;
|
|
|
|
|
2007-07-29 15:21:25 +00:00
|
|
|
// resample if needed
|
|
|
|
unsigned char *texdata = (unsigned char *)data;
|
|
|
|
unsigned char *tmpdata = 0;
|
2007-07-29 15:39:49 +00:00
|
|
|
if(config.gfx_texture_quality==0)
|
2007-07-29 15:21:25 +00:00
|
|
|
{
|
|
|
|
if(w > 16 && h > 16 && format == IMG_RGBA)
|
|
|
|
{
|
2007-07-29 15:38:20 +00:00
|
|
|
w/=2;
|
|
|
|
h/=2;
|
2007-07-29 15:21:25 +00:00
|
|
|
unsigned char *tmpdata = (unsigned char *)mem_alloc(w*h*4, 1);
|
|
|
|
int c = 0;
|
2007-08-22 07:52:33 +00:00
|
|
|
int x, y;
|
|
|
|
for(y = 0; y < h; y++)
|
|
|
|
for(x = 0; x < w; x++, c++)
|
2007-07-29 15:21:25 +00:00
|
|
|
{
|
2007-07-29 15:38:20 +00:00
|
|
|
tmpdata[c*4] = sample(w*2, h*2, texdata, x*2,y*2, 0);
|
|
|
|
tmpdata[c*4+1] = sample(w*2, h*2, texdata, x*2,y*2, 1);
|
|
|
|
tmpdata[c*4+2] = sample(w*2, h*2, texdata, x*2,y*2, 2);
|
|
|
|
tmpdata[c*4+3] = sample(w*2, h*2, texdata, x*2,y*2, 3);
|
2007-07-29 15:21:25 +00:00
|
|
|
}
|
|
|
|
texdata = tmpdata;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-08-14 18:37:16 +00:00
|
|
|
if(config.debug)
|
|
|
|
dbg_msg("gfx", "%d = %dx%d", tex, w, h);
|
2007-07-29 15:21:25 +00:00
|
|
|
|
2007-08-22 07:52:33 +00:00
|
|
|
// upload texture
|
|
|
|
int oglformat = 0;
|
|
|
|
if(config.gfx_texture_compression)
|
2007-07-22 09:15:34 +00:00
|
|
|
{
|
2007-08-22 07:52:33 +00:00
|
|
|
oglformat = GL_COMPRESSED_RGBA_ARB;
|
2007-07-29 15:21:25 +00:00
|
|
|
if(format == IMG_RGB)
|
2007-08-22 07:52:33 +00:00
|
|
|
oglformat = GL_COMPRESSED_RGB_ARB;
|
2007-07-22 09:15:34 +00:00
|
|
|
}
|
2007-07-29 15:21:25 +00:00
|
|
|
else
|
|
|
|
{
|
2007-08-22 07:52:33 +00:00
|
|
|
oglformat = GL_RGBA;
|
2007-07-29 15:21:25 +00:00
|
|
|
if(format == IMG_RGB)
|
2007-08-22 07:52:33 +00:00
|
|
|
oglformat = GL_RGB;
|
2007-07-29 15:21:25 +00:00
|
|
|
}
|
2007-08-22 07:52:33 +00:00
|
|
|
|
|
|
|
glGenTextures(1, &textures[tex].tex);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, textures[tex].tex);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
|
|
|
gluBuild2DMipmaps(GL_TEXTURE_2D, oglformat, w, h, oglformat, GL_UNSIGNED_BYTE, texdata);
|
2007-07-29 15:21:25 +00:00
|
|
|
|
2007-08-22 07:52:33 +00:00
|
|
|
// calculate memory usage
|
2007-07-30 19:46:31 +00:00
|
|
|
textures[tex].memsize = w*h*4;
|
|
|
|
if(mipmap)
|
|
|
|
{
|
|
|
|
while(w > 2 && h > 2)
|
|
|
|
{
|
|
|
|
w>>=1;
|
|
|
|
h>>=1;
|
|
|
|
textures[tex].memsize += w*h*4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
memory_usage += textures[tex].memsize;
|
2007-07-29 15:21:25 +00:00
|
|
|
mem_free(tmpdata);
|
2007-05-22 15:03:32 +00:00
|
|
|
return tex;
|
|
|
|
}
|
2007-07-22 11:46:25 +00:00
|
|
|
/*
|
|
|
|
int gfx_load_mip_texture_raw(int w, int h, int format, const void *data)
|
|
|
|
{
|
|
|
|
// grab texture
|
|
|
|
int tex = first_free_texture;
|
|
|
|
first_free_texture = textures[tex].next;
|
|
|
|
textures[tex].next = -1;
|
|
|
|
|
|
|
|
// set data and return
|
|
|
|
// TODO: should be RGBA, not BGRA
|
|
|
|
dbg_msg("gfx", "%d = %dx%d", tex, w, h);
|
|
|
|
dbg_assert(format == IMG_RGBA, "not an RGBA image");
|
2007-05-22 15:03:32 +00:00
|
|
|
|
2007-07-22 11:46:25 +00:00
|
|
|
unsigned mip_w = w;
|
|
|
|
unsigned mip_h = h;
|
|
|
|
unsigned level = 0;
|
|
|
|
const unsigned char *ptr = (const unsigned char*)data;
|
|
|
|
while(mip_w > 0 && mip_h > 0)
|
|
|
|
{
|
|
|
|
dbg_msg("gfx mip", "%d = %dx%d", level, mip_w, mip_h);
|
|
|
|
textures[tex].tex.data2d_mip(mip_w, mip_h, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, level, ptr);
|
|
|
|
level++;
|
|
|
|
ptr = ptr + mip_w*mip_h*4;
|
|
|
|
mip_w = mip_w>>1;
|
|
|
|
mip_h = mip_h>>1;
|
|
|
|
}
|
|
|
|
return tex;
|
|
|
|
}
|
|
|
|
*/
|
2007-05-22 15:03:32 +00:00
|
|
|
// simple uncompressed RGBA loaders
|
2007-05-27 00:47:07 +00:00
|
|
|
int gfx_load_texture(const char *filename)
|
2007-05-22 15:03:32 +00:00
|
|
|
{
|
2007-05-27 00:47:07 +00:00
|
|
|
int l = strlen(filename);
|
|
|
|
if(l < 3)
|
|
|
|
return 0;
|
2007-08-22 07:52:33 +00:00
|
|
|
IMAGE_INFO img;
|
2007-07-24 22:53:43 +00:00
|
|
|
if(gfx_load_png(&img, filename))
|
2007-05-22 15:03:32 +00:00
|
|
|
{
|
2007-07-24 22:53:43 +00:00
|
|
|
int id = gfx_load_texture_raw(img.width, img.height, img.format, img.data);
|
|
|
|
mem_free(img.data);
|
|
|
|
return id;
|
2007-05-22 15:03:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2007-08-22 07:52:33 +00:00
|
|
|
int gfx_load_png(IMAGE_INFO *img, const char *filename)
|
2007-05-27 00:47:07 +00:00
|
|
|
{
|
|
|
|
// open file for reading
|
|
|
|
png_init(0,0);
|
|
|
|
|
|
|
|
png_t png;
|
|
|
|
if(png_open_file(&png, filename) != PNG_NO_ERROR)
|
|
|
|
{
|
|
|
|
dbg_msg("game/png", "failed to open file. filename='%s'", filename);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(png.depth != 8 || (png.color_type != PNG_TRUECOLOR && png.color_type != PNG_TRUECOLOR_ALPHA))
|
|
|
|
{
|
|
|
|
dbg_msg("game/png", "invalid format. filename='%s'", filename);
|
|
|
|
png_close_file(&png);
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned char *buffer = (unsigned char *)mem_alloc(png.width * png.height * png.bpp, 1);
|
|
|
|
png_get_data(&png, buffer);
|
|
|
|
png_close_file(&png);
|
|
|
|
|
|
|
|
img->width = png.width;
|
|
|
|
img->height = png.height;
|
|
|
|
if(png.color_type == PNG_TRUECOLOR)
|
|
|
|
img->format = IMG_RGB;
|
|
|
|
else if(png.color_type == PNG_TRUECOLOR_ALPHA)
|
|
|
|
img->format = IMG_RGBA;
|
|
|
|
img->data = buffer;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2007-05-22 15:03:32 +00:00
|
|
|
void gfx_shutdown()
|
|
|
|
{
|
2007-07-24 22:53:43 +00:00
|
|
|
if (vertices)
|
|
|
|
mem_free(vertices);
|
2007-08-22 07:52:33 +00:00
|
|
|
glfwCloseWindow();
|
|
|
|
glfwTerminate();
|
2007-05-22 15:03:32 +00:00
|
|
|
}
|
|
|
|
|
2007-08-04 09:20:59 +00:00
|
|
|
void gfx_screenshot()
|
|
|
|
{
|
|
|
|
do_screenshot = 1;
|
|
|
|
}
|
|
|
|
|
2007-05-22 15:03:32 +00:00
|
|
|
void gfx_swap()
|
|
|
|
{
|
2007-08-04 09:20:59 +00:00
|
|
|
if(do_screenshot)
|
|
|
|
{
|
|
|
|
// fetch image data
|
|
|
|
int w = screen_width;
|
|
|
|
int h = screen_height;
|
|
|
|
unsigned char *pixel_data = (unsigned char *)mem_alloc(w*(h+1)*3, 1);
|
|
|
|
unsigned char *temp_row = pixel_data+w*h*3;
|
|
|
|
glReadPixels(0,0, w, h, GL_RGB, GL_UNSIGNED_BYTE, pixel_data);
|
|
|
|
|
|
|
|
// flip the pixel because opengl works from bottom left corner
|
2007-08-22 07:52:33 +00:00
|
|
|
int y;
|
|
|
|
for(y = 0; y < h/2; y++)
|
2007-08-04 09:20:59 +00:00
|
|
|
{
|
|
|
|
mem_copy(temp_row, pixel_data+y*w*3, w*3);
|
|
|
|
mem_copy(pixel_data+y*w*3, pixel_data+(h-y-1)*w*3, w*3);
|
|
|
|
mem_copy(pixel_data+(h-y-1)*w*3, temp_row,w*3);
|
|
|
|
}
|
|
|
|
|
|
|
|
// find filename
|
|
|
|
char filename[64];
|
|
|
|
{
|
|
|
|
static int index = 1;
|
|
|
|
for(; index < 1000; index++)
|
|
|
|
{
|
|
|
|
sprintf(filename, "screenshot%04d.png", index);
|
|
|
|
IOHANDLE io = io_open(filename, IOFLAG_READ);
|
|
|
|
if(io)
|
|
|
|
io_close(io);
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// save png
|
|
|
|
png_t png;
|
|
|
|
png_open_file_write(&png, filename);
|
|
|
|
png_set_data(&png, w, h, 8, PNG_TRUECOLOR, (unsigned char *)pixel_data);
|
|
|
|
png_close_file(&png);
|
|
|
|
|
|
|
|
// clean up
|
|
|
|
mem_free(pixel_data);
|
|
|
|
do_screenshot = 0;
|
|
|
|
}
|
|
|
|
|
2007-08-22 07:52:33 +00:00
|
|
|
glfwSwapBuffers();
|
|
|
|
glfwPollEvents();
|
2007-05-22 15:03:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int gfx_screenwidth()
|
|
|
|
{
|
2007-08-04 09:20:59 +00:00
|
|
|
return screen_width;
|
2007-05-22 15:03:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int gfx_screenheight()
|
|
|
|
{
|
2007-08-04 09:20:59 +00:00
|
|
|
return screen_height;
|
2007-05-22 15:03:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void gfx_texture_set(int slot)
|
|
|
|
{
|
2007-09-23 18:27:04 +00:00
|
|
|
dbg_assert(drawing == 0, "called gfx_texture_set within begin");
|
2007-05-22 15:03:32 +00:00
|
|
|
if(slot == -1)
|
2007-08-22 07:52:33 +00:00
|
|
|
glDisable(GL_TEXTURE_2D);
|
2007-05-22 15:03:32 +00:00
|
|
|
else
|
2007-08-22 07:52:33 +00:00
|
|
|
{
|
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, textures[slot].tex);
|
|
|
|
}
|
2007-05-22 15:03:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void gfx_clear(float r, float g, float b)
|
|
|
|
{
|
|
|
|
glClearColor(r,g,b,1.0f);
|
2007-08-22 07:52:33 +00:00
|
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
2007-05-22 15:03:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void gfx_mapscreen(float tl_x, float tl_y, float br_x, float br_y)
|
|
|
|
{
|
2007-07-22 12:01:20 +00:00
|
|
|
screen_x0 = tl_x;
|
|
|
|
screen_y0 = tl_y;
|
|
|
|
screen_x1 = br_x;
|
|
|
|
screen_y1 = br_y;
|
2007-08-22 07:52:33 +00:00
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glLoadIdentity();
|
|
|
|
glOrtho(tl_x, br_x, br_y, tl_y, 1.0f, 10.f);
|
2007-05-22 15:03:32 +00:00
|
|
|
}
|
|
|
|
|
2007-07-22 12:01:20 +00:00
|
|
|
void gfx_getscreen(float *tl_x, float *tl_y, float *br_x, float *br_y)
|
|
|
|
{
|
|
|
|
*tl_x = screen_x0;
|
|
|
|
*tl_y = screen_y0;
|
|
|
|
*br_x = screen_x1;
|
|
|
|
*br_y = screen_y1;
|
|
|
|
}
|
|
|
|
|
2007-05-22 15:03:32 +00:00
|
|
|
void gfx_setoffset(float x, float y)
|
|
|
|
{
|
2007-08-22 07:52:33 +00:00
|
|
|
//const float scale = 1.0f;
|
|
|
|
//mat4 mat = mat4::identity;
|
|
|
|
//mat.m[0] = scale;
|
|
|
|
//mat.m[5] = scale;
|
|
|
|
//mat.m[10] = scale;
|
|
|
|
//mat.m[12] = x*scale;
|
|
|
|
//mat.m[13] = y*scale;
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glLoadIdentity();
|
|
|
|
glTranslatef(x, y, 0);
|
2007-05-22 15:03:32 +00:00
|
|
|
}
|
|
|
|
|
2007-07-24 22:53:43 +00:00
|
|
|
|
2007-05-22 15:03:32 +00:00
|
|
|
void gfx_quads_begin()
|
|
|
|
{
|
2007-09-23 18:27:04 +00:00
|
|
|
dbg_assert(drawing == 0, "called quads_begin twice");
|
|
|
|
drawing = DRAWING_QUADS;
|
2007-05-22 15:03:32 +00:00
|
|
|
|
|
|
|
gfx_quads_setsubset(0,0,1,1);
|
|
|
|
gfx_quads_setrotation(0);
|
2007-09-23 18:27:04 +00:00
|
|
|
gfx_setcolor(1,1,1,1);
|
2007-05-22 15:03:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void gfx_quads_end()
|
|
|
|
{
|
2007-09-23 18:27:04 +00:00
|
|
|
dbg_assert(drawing == DRAWING_QUADS, "called quads_end without begin");
|
|
|
|
flush();
|
|
|
|
drawing = 0;
|
2007-05-22 15:03:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void gfx_quads_setrotation(float angle)
|
|
|
|
{
|
2007-09-23 18:27:04 +00:00
|
|
|
dbg_assert(drawing == DRAWING_QUADS, "called gfx_quads_setrotation without begin");
|
2007-05-22 15:03:32 +00:00
|
|
|
rotation = angle;
|
|
|
|
}
|
|
|
|
|
2007-09-23 18:27:04 +00:00
|
|
|
void gfx_setcolorvertex(int i, float r, float g, float b, float a)
|
2007-05-22 15:03:32 +00:00
|
|
|
{
|
2007-09-23 18:27:04 +00:00
|
|
|
dbg_assert(drawing != 0, "called gfx_quads_setcolorvertex without begin");
|
2007-07-24 22:53:43 +00:00
|
|
|
color[i].r = r;
|
|
|
|
color[i].g = g;
|
|
|
|
color[i].b = b;
|
|
|
|
color[i].a = a;
|
2007-05-22 15:03:32 +00:00
|
|
|
}
|
|
|
|
|
2007-09-23 18:27:04 +00:00
|
|
|
void gfx_setcolor(float r, float g, float b, float a)
|
2007-05-22 15:03:32 +00:00
|
|
|
{
|
2007-09-23 18:27:04 +00:00
|
|
|
dbg_assert(drawing != 0, "called gfx_quads_setcolor without begin");
|
|
|
|
gfx_setcolorvertex(0, r, g, b, a);
|
|
|
|
gfx_setcolorvertex(1, r, g, b, a);
|
|
|
|
gfx_setcolorvertex(2, r, g, b, a);
|
|
|
|
gfx_setcolorvertex(3, r, g, b, a);
|
2007-05-22 15:03:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void gfx_quads_setsubset(float tl_u, float tl_v, float br_u, float br_v)
|
|
|
|
{
|
2007-09-23 18:27:04 +00:00
|
|
|
dbg_assert(drawing == DRAWING_QUADS, "called gfx_quads_setsubset without begin");
|
2007-05-22 15:03:32 +00:00
|
|
|
|
2007-08-22 07:52:33 +00:00
|
|
|
texture[0].u = tl_u;
|
|
|
|
texture[0].v = tl_v;
|
2007-05-22 15:03:32 +00:00
|
|
|
//g_pVertices[g_iVertexEnd].tex.u = tl_u;
|
|
|
|
//g_pVertices[g_iVertexEnd].tex.v = tl_v;
|
|
|
|
|
2007-08-22 07:52:33 +00:00
|
|
|
texture[1].u = br_u;
|
|
|
|
texture[1].v = tl_v;
|
2007-05-22 15:03:32 +00:00
|
|
|
//g_pVertices[g_iVertexEnd + 2].tex.u = br_u;
|
|
|
|
//g_pVertices[g_iVertexEnd + 2].tex.v = tl_v;
|
|
|
|
|
2007-08-22 07:52:33 +00:00
|
|
|
texture[2].u = br_u;
|
|
|
|
texture[2].v = br_v;
|
2007-05-22 15:03:32 +00:00
|
|
|
//g_pVertices[g_iVertexEnd + 1].tex.u = tl_u;
|
|
|
|
//g_pVertices[g_iVertexEnd + 1].tex.v = br_v;
|
|
|
|
|
2007-08-22 07:52:33 +00:00
|
|
|
texture[3].u = tl_u;
|
|
|
|
texture[3].v = br_v;
|
2007-05-22 15:03:32 +00:00
|
|
|
//g_pVertices[g_iVertexEnd + 3].tex.u = br_u;
|
|
|
|
//g_pVertices[g_iVertexEnd + 3].tex.v = br_v;
|
|
|
|
}
|
|
|
|
|
2007-08-22 07:52:33 +00:00
|
|
|
static void rotate(VEC3 *center, VEC3 *point)
|
2007-05-22 15:03:32 +00:00
|
|
|
{
|
2007-08-22 07:52:33 +00:00
|
|
|
float x = point->x - center->x;
|
|
|
|
float y = point->y - center->y;
|
|
|
|
point->x = x * cosf(rotation) - y * sinf(rotation) + center->x;
|
|
|
|
point->y = x * sinf(rotation) + y * cosf(rotation) + center->y;
|
2007-05-22 15:03:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void gfx_quads_draw(float x, float y, float w, float h)
|
|
|
|
{
|
|
|
|
gfx_quads_drawTL(x-w/2, y-h/2,w,h);
|
|
|
|
}
|
|
|
|
|
|
|
|
void gfx_quads_drawTL(float x, float y, float width, float height)
|
|
|
|
{
|
2007-09-23 18:27:04 +00:00
|
|
|
dbg_assert(drawing == DRAWING_QUADS, "called quads_draw without begin");
|
2007-05-22 15:03:32 +00:00
|
|
|
|
2007-08-22 07:52:33 +00:00
|
|
|
VEC3 center;
|
2007-05-22 15:03:32 +00:00
|
|
|
center.x = x + width/2;
|
|
|
|
center.y = y + height/2;
|
|
|
|
center.z = 0;
|
|
|
|
|
2007-07-24 22:53:43 +00:00
|
|
|
vertices[num_vertices].pos.x = x;
|
|
|
|
vertices[num_vertices].pos.y = y;
|
2007-08-22 07:52:33 +00:00
|
|
|
vertices[num_vertices].tex = texture[0];
|
2007-07-24 22:53:43 +00:00
|
|
|
vertices[num_vertices].color = color[0];
|
2007-08-22 07:52:33 +00:00
|
|
|
rotate(¢er, &vertices[num_vertices].pos);
|
2007-07-24 22:53:43 +00:00
|
|
|
|
|
|
|
vertices[num_vertices + 1].pos.x = x+width;
|
|
|
|
vertices[num_vertices + 1].pos.y = y;
|
2007-08-22 07:52:33 +00:00
|
|
|
vertices[num_vertices + 1].tex = texture[1];
|
2007-07-24 22:53:43 +00:00
|
|
|
vertices[num_vertices + 1].color = color[1];
|
2007-08-22 07:52:33 +00:00
|
|
|
rotate(¢er, &vertices[num_vertices + 1].pos);
|
2007-07-24 22:53:43 +00:00
|
|
|
|
|
|
|
vertices[num_vertices + 2].pos.x = x + width;
|
|
|
|
vertices[num_vertices + 2].pos.y = y+height;
|
2007-08-22 07:52:33 +00:00
|
|
|
vertices[num_vertices + 2].tex = texture[2];
|
2007-07-24 22:53:43 +00:00
|
|
|
vertices[num_vertices + 2].color = color[2];
|
2007-08-22 07:52:33 +00:00
|
|
|
rotate(¢er, &vertices[num_vertices + 2].pos);
|
2007-07-24 22:53:43 +00:00
|
|
|
|
|
|
|
vertices[num_vertices + 3].pos.x = x;
|
|
|
|
vertices[num_vertices + 3].pos.y = y+height;
|
2007-08-22 07:52:33 +00:00
|
|
|
vertices[num_vertices + 3].tex = texture[3];
|
2007-07-24 22:53:43 +00:00
|
|
|
vertices[num_vertices + 3].color = color[3];
|
2007-08-22 07:52:33 +00:00
|
|
|
rotate(¢er, &vertices[num_vertices + 3].pos);
|
2007-05-22 15:03:32 +00:00
|
|
|
|
2007-09-23 18:27:04 +00:00
|
|
|
draw_quad();
|
2007-05-22 15:03:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void gfx_quads_draw_freeform(
|
|
|
|
float x0, float y0,
|
|
|
|
float x1, float y1,
|
|
|
|
float x2, float y2,
|
|
|
|
float x3, float y3)
|
|
|
|
{
|
2007-09-23 18:27:04 +00:00
|
|
|
dbg_assert(drawing == DRAWING_QUADS, "called quads_draw_freeform without begin");
|
2007-05-22 15:03:32 +00:00
|
|
|
|
2007-07-24 22:53:43 +00:00
|
|
|
vertices[num_vertices].pos.x = x0;
|
|
|
|
vertices[num_vertices].pos.y = y0;
|
2007-08-22 07:52:33 +00:00
|
|
|
vertices[num_vertices].tex = texture[0];
|
2007-07-24 22:53:43 +00:00
|
|
|
vertices[num_vertices].color = color[0];
|
|
|
|
|
|
|
|
vertices[num_vertices + 1].pos.x = x1;
|
|
|
|
vertices[num_vertices + 1].pos.y = y1;
|
2007-08-22 07:52:33 +00:00
|
|
|
vertices[num_vertices + 1].tex = texture[1];
|
2007-07-24 22:53:43 +00:00
|
|
|
vertices[num_vertices + 1].color = color[1];
|
|
|
|
|
|
|
|
vertices[num_vertices + 2].pos.x = x3;
|
|
|
|
vertices[num_vertices + 2].pos.y = y3;
|
2007-08-22 07:52:33 +00:00
|
|
|
vertices[num_vertices + 2].tex = texture[2];
|
2007-07-24 22:53:43 +00:00
|
|
|
vertices[num_vertices + 2].color = color[2];
|
|
|
|
|
|
|
|
vertices[num_vertices + 3].pos.x = x2;
|
|
|
|
vertices[num_vertices + 3].pos.y = y2;
|
2007-08-22 07:52:33 +00:00
|
|
|
vertices[num_vertices + 3].tex = texture[3];
|
2007-07-24 22:53:43 +00:00
|
|
|
vertices[num_vertices + 3].color = color[3];
|
2007-05-22 15:03:32 +00:00
|
|
|
|
2007-09-23 18:27:04 +00:00
|
|
|
draw_quad();
|
2007-05-22 15:03:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void gfx_quads_text(float x, float y, float size, const char *text)
|
|
|
|
{
|
|
|
|
gfx_quads_begin();
|
2007-07-15 13:25:10 +00:00
|
|
|
float startx = x;
|
2007-05-22 15:03:32 +00:00
|
|
|
while(*text)
|
|
|
|
{
|
|
|
|
char c = *text;
|
|
|
|
text++;
|
|
|
|
|
2007-07-15 13:25:10 +00:00
|
|
|
if(c == '\n')
|
|
|
|
{
|
|
|
|
x = startx;
|
|
|
|
y += size;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gfx_quads_setsubset(
|
|
|
|
(c%16)/16.0f,
|
|
|
|
(c/16)/16.0f,
|
|
|
|
(c%16)/16.0f+1.0f/16.0f,
|
|
|
|
(c/16)/16.0f+1.0f/16.0f);
|
|
|
|
|
|
|
|
gfx_quads_drawTL(x,y,size,size);
|
|
|
|
x += size/2;
|
|
|
|
}
|
2007-05-22 15:03:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
gfx_quads_end();
|
|
|
|
}
|
|
|
|
|
2007-08-22 07:52:33 +00:00
|
|
|
typedef struct
|
2007-05-22 15:03:32 +00:00
|
|
|
{
|
|
|
|
float m_CharStartTable[256];
|
|
|
|
float m_CharEndTable[256];
|
|
|
|
int font_texture;
|
2007-08-22 07:52:33 +00:00
|
|
|
} pretty_font;
|
2007-05-22 15:03:32 +00:00
|
|
|
|
|
|
|
pretty_font default_font =
|
|
|
|
{
|
|
|
|
{
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
0, 0.421875, 0.359375, 0.265625, 0.25, 0.1875, 0.25, 0.4375, 0.390625, 0.390625, 0.34375, 0.28125, 0.421875, 0.390625, 0.4375, 0.203125,
|
|
|
|
0.265625, 0.28125, 0.28125, 0.265625, 0.25, 0.28125, 0.28125, 0.265625, 0.28125, 0.265625, 0.4375, 0.421875, 0.3125, 0.28125, 0.3125, 0.3125,
|
|
|
|
0.25, 0.234375, 0.28125, 0.265625, 0.265625, 0.296875, 0.3125, 0.25, 0.25, 0.421875, 0.28125, 0.265625, 0.328125, 0.171875, 0.234375, 0.25,
|
|
|
|
0.28125, 0.234375, 0.265625, 0.265625, 0.28125, 0.265625, 0.234375, 0.09375, 0.234375, 0.234375, 0.265625, 0.390625, 0.203125, 0.390625, 0.296875, 0.28125,
|
|
|
|
0.375, 0.3125, 0.3125, 0.3125, 0.296875, 0.3125, 0.359375, 0.296875, 0.3125, 0.4375, 0.390625, 0.328125, 0.4375, 0.203125, 0.3125, 0.296875,
|
|
|
|
0.3125, 0.296875, 0.359375, 0.3125, 0.328125, 0.3125, 0.296875, 0.203125, 0.296875, 0.296875, 0.328125, 0.375, 0.421875, 0.375, 0.28125, 0.3125,
|
|
|
|
0.3125, 0.3125, 0.3125, 0.3125, 0.3125, 0.3125, 0.3125, 0.3125, 0.3125, 0.3125, 0.3125, 0.3125, 0.3125, 0.3125, 0.3125, 0.3125,
|
|
|
|
0.3125, 0.3125, 0.3125, 0.3125, 0.3125, 0.3125, 0.3125, 0.3125, 0.3125, 0.3125, 0.3125, 0.3125, 0.3125, 0.3125, 0.3125, 0.3125,
|
|
|
|
0, 0.421875, 0.3125, 0.265625, 0.25, 0.25, 0.421875, 0.265625, 0.375, 0.21875, 0.375, 0.328125, 0.3125, 0, 0.21875, 0.28125,
|
|
|
|
0.359375, 0.28125, 0.34375, 0.34375, 0.421875, 0.3125, 0.265625, 0.421875, 0.421875, 0.34375, 0.375, 0.328125, 0.125, 0.125, 0.125, 0.296875,
|
|
|
|
0.234375, 0.234375, 0.234375, 0.234375, 0.234375, 0.234375, 0.109375, 0.265625, 0.296875, 0.296875, 0.296875, 0.296875, 0.375, 0.421875, 0.359375, 0.390625,
|
|
|
|
0.21875, 0.234375, 0.25, 0.25, 0.25, 0.25, 0.25, 0.296875, 0.21875, 0.265625, 0.265625, 0.265625, 0.265625, 0.234375, 0.28125, 0.3125,
|
|
|
|
0.3125, 0.3125, 0.3125, 0.3125, 0.3125, 0.3125, 0.1875, 0.3125, 0.3125, 0.3125, 0.3125, 0.3125, 0.375, 0.421875, 0.359375, 0.390625,
|
|
|
|
0.3125, 0.3125, 0.296875, 0.296875, 0.296875, 0.296875, 0.296875, 0.28125, 0.28125, 0.3125, 0.3125, 0.3125, 0.3125, 0.296875, 0.3125, 0.296875,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
0.2, 0.5625, 0.625, 0.71875, 0.734375, 0.796875, 0.765625, 0.546875, 0.59375, 0.59375, 0.65625, 0.703125, 0.546875, 0.59375, 0.5625, 0.6875,
|
|
|
|
0.71875, 0.609375, 0.703125, 0.703125, 0.71875, 0.703125, 0.703125, 0.6875, 0.703125, 0.703125, 0.5625, 0.546875, 0.671875, 0.703125, 0.671875, 0.671875,
|
|
|
|
0.734375, 0.75, 0.734375, 0.734375, 0.734375, 0.6875, 0.6875, 0.734375, 0.71875, 0.5625, 0.65625, 0.765625, 0.703125, 0.8125, 0.75, 0.734375,
|
|
|
|
0.734375, 0.765625, 0.71875, 0.71875, 0.703125, 0.71875, 0.75, 0.890625, 0.75, 0.75, 0.71875, 0.59375, 0.6875, 0.59375, 0.6875, 0.703125,
|
|
|
|
0.5625, 0.671875, 0.6875, 0.671875, 0.671875, 0.671875, 0.625, 0.671875, 0.671875, 0.5625, 0.546875, 0.703125, 0.5625, 0.78125, 0.671875, 0.671875,
|
|
|
|
0.6875, 0.671875, 0.65625, 0.671875, 0.65625, 0.671875, 0.6875, 0.78125, 0.6875, 0.671875, 0.65625, 0.609375, 0.546875, 0.609375, 0.703125, 0.671875,
|
|
|
|
0.671875, 0.671875, 0.671875, 0.671875, 0.671875, 0.671875, 0.671875, 0.671875, 0.671875, 0.671875, 0.671875, 0.671875, 0.671875, 0.671875, 0.671875, 0.671875,
|
|
|
|
0.671875, 0.671875, 0.671875, 0.671875, 0.671875, 0.671875, 0.671875, 0.671875, 0.671875, 0.671875, 0.671875, 0.671875, 0.671875, 0.671875, 0.671875, 0.671875,
|
|
|
|
0, 0.5625, 0.671875, 0.734375, 0.734375, 0.734375, 0.546875, 0.71875, 0.609375, 0.765625, 0.609375, 0.65625, 0.671875, 0, 0.765625, 0.703125,
|
|
|
|
0.625, 0.703125, 0.640625, 0.640625, 0.609375, 0.671875, 0.703125, 0.546875, 0.5625, 0.578125, 0.609375, 0.65625, 0.859375, 0.859375, 0.859375, 0.671875,
|
|
|
|
0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.84375, 0.734375, 0.6875, 0.6875, 0.6875, 0.6875, 0.5625, 0.609375, 0.640625, 0.59375,
|
|
|
|
0.734375, 0.75, 0.734375, 0.734375, 0.734375, 0.734375, 0.734375, 0.6875, 0.765625, 0.71875, 0.71875, 0.71875, 0.71875, 0.75, 0.734375, 0.6875,
|
|
|
|
0.671875, 0.671875, 0.671875, 0.671875, 0.671875, 0.671875, 0.796875, 0.671875, 0.671875, 0.671875, 0.671875, 0.671875, 0.5625, 0.609375, 0.625, 0.59375,
|
|
|
|
0.6875, 0.671875, 0.671875, 0.671875, 0.671875, 0.671875, 0.671875, 0.703125, 0.703125, 0.671875, 0.671875, 0.671875, 0.671875, 0.671875, 0.6875, 0.671875,
|
|
|
|
},
|
|
|
|
0
|
|
|
|
};
|
|
|
|
|
2007-06-10 17:25:08 +00:00
|
|
|
double extra_kerning[256*256] = {0};
|
|
|
|
|
2007-05-22 15:03:32 +00:00
|
|
|
pretty_font *current_font = &default_font;
|
|
|
|
|
2007-08-14 18:37:16 +00:00
|
|
|
static int word_length(const char *text)
|
2007-05-22 15:03:32 +00:00
|
|
|
{
|
2007-08-14 18:37:16 +00:00
|
|
|
int s = 1;
|
|
|
|
while(1)
|
|
|
|
{
|
|
|
|
if(*text == 0)
|
|
|
|
return s-1;
|
|
|
|
if(*text == '\n' || *text == '\t' || *text == ' ')
|
|
|
|
return s;
|
|
|
|
text++;
|
|
|
|
s++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
float gfx_pretty_text_raw(float x, float y, float size, const char *text_, int length)
|
|
|
|
{
|
|
|
|
const unsigned char *text = (unsigned char *)text_;
|
2007-05-22 15:03:32 +00:00
|
|
|
const float spacing = 0.05f;
|
2007-07-14 13:09:42 +00:00
|
|
|
gfx_texture_set(current_font->font_texture);
|
2007-05-22 15:03:32 +00:00
|
|
|
gfx_quads_begin();
|
|
|
|
|
2007-08-14 18:37:16 +00:00
|
|
|
if(length < 0)
|
|
|
|
length = strlen(text_);
|
2007-07-15 13:25:10 +00:00
|
|
|
|
2007-08-14 18:37:16 +00:00
|
|
|
while(length)
|
2007-05-22 15:03:32 +00:00
|
|
|
{
|
2007-05-24 20:54:08 +00:00
|
|
|
const int c = *text;
|
2007-08-14 18:37:16 +00:00
|
|
|
text++;
|
|
|
|
|
|
|
|
const float width = current_font->m_CharEndTable[c] - current_font->m_CharStartTable[c];
|
|
|
|
|
|
|
|
x -= size * current_font->m_CharStartTable[c];
|
2007-05-22 15:03:32 +00:00
|
|
|
|
2007-08-14 18:37:16 +00:00
|
|
|
gfx_quads_setsubset(
|
|
|
|
(c%16)/16.0f, // startx
|
|
|
|
(c/16)/16.0f, // starty
|
|
|
|
(c%16)/16.0f+1.0f/16.0f, // endx
|
|
|
|
(c/16)/16.0f+1.0f/16.0f); // endy
|
2007-05-22 15:03:32 +00:00
|
|
|
|
2007-08-14 18:37:16 +00:00
|
|
|
gfx_quads_drawTL(x, y, size, size);
|
2007-05-22 15:03:32 +00:00
|
|
|
|
2007-08-14 18:37:16 +00:00
|
|
|
double x_nudge = 0;
|
|
|
|
if(length > 1 && text[1])
|
|
|
|
x_nudge = extra_kerning[text[0] + text[1] * 256];
|
2007-06-10 17:25:08 +00:00
|
|
|
|
2007-08-14 18:37:16 +00:00
|
|
|
x += (width + current_font->m_CharStartTable[c] + spacing + x_nudge) * size;
|
|
|
|
length--;
|
|
|
|
}
|
2007-07-15 13:25:10 +00:00
|
|
|
|
2007-08-14 18:37:16 +00:00
|
|
|
gfx_quads_end();
|
|
|
|
|
|
|
|
return x;
|
|
|
|
}
|
2007-08-10 11:03:16 +00:00
|
|
|
|
2007-08-14 18:37:16 +00:00
|
|
|
void gfx_pretty_text(float x, float y, float size, const char *text, int max_width)
|
|
|
|
{
|
|
|
|
if(max_width == -1)
|
|
|
|
gfx_pretty_text_raw(x, y, size, text, -1);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
float startx = x;
|
|
|
|
while(*text)
|
|
|
|
{
|
|
|
|
int wlen = word_length(text);
|
|
|
|
float w = gfx_pretty_text_width(size, text, wlen);
|
|
|
|
if(x+w-startx > max_width)
|
2007-08-10 11:03:16 +00:00
|
|
|
{
|
2007-08-14 18:37:16 +00:00
|
|
|
y += size-2;
|
2007-08-10 11:03:16 +00:00
|
|
|
x = startx;
|
|
|
|
}
|
2007-08-14 18:37:16 +00:00
|
|
|
|
|
|
|
x = gfx_pretty_text_raw(x, y, size, text, wlen);
|
|
|
|
|
|
|
|
text += wlen;
|
2007-07-15 13:25:10 +00:00
|
|
|
}
|
2007-05-22 15:03:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-08-14 18:37:16 +00:00
|
|
|
float gfx_pretty_text_width(float size, const char *text_, int length)
|
2007-05-22 15:03:32 +00:00
|
|
|
{
|
|
|
|
const float spacing = 0.05f;
|
2007-06-10 17:25:08 +00:00
|
|
|
float w = 0.0f;
|
2007-08-14 18:37:16 +00:00
|
|
|
const unsigned char *text = (unsigned char *)text_;
|
2007-05-22 15:03:32 +00:00
|
|
|
|
2007-08-14 18:37:16 +00:00
|
|
|
const unsigned char *stop;
|
2007-07-28 17:44:12 +00:00
|
|
|
if (length == -1)
|
2007-08-14 18:37:16 +00:00
|
|
|
stop = text + strlen((char*)text);
|
2007-07-28 17:44:12 +00:00
|
|
|
else
|
|
|
|
stop = text + length;
|
|
|
|
|
|
|
|
while (text < stop)
|
2007-05-22 15:03:32 +00:00
|
|
|
{
|
2007-06-10 17:25:08 +00:00
|
|
|
const int c = *text;
|
|
|
|
const float width = current_font->m_CharEndTable[c] - current_font->m_CharStartTable[c];
|
|
|
|
|
|
|
|
double x_nudge = 0;
|
|
|
|
if (text[1])
|
|
|
|
x_nudge = extra_kerning[text[0] + text[1] * 256];
|
|
|
|
|
|
|
|
w += (width + spacing + x_nudge) * size;
|
|
|
|
|
|
|
|
text++;
|
2007-05-22 15:03:32 +00:00
|
|
|
}
|
|
|
|
|
2007-06-10 17:25:08 +00:00
|
|
|
return w;
|
2007-05-22 15:03:32 +00:00
|
|
|
}
|
2007-09-23 18:27:04 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void gfx_lines_begin()
|
|
|
|
{
|
|
|
|
dbg_assert(drawing == 0, "called begin twice");
|
|
|
|
drawing = DRAWING_LINES;
|
|
|
|
gfx_setcolor(1,1,1,1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void gfx_lines_end()
|
|
|
|
{
|
|
|
|
dbg_assert(drawing == DRAWING_LINES, "called end without begin");
|
|
|
|
flush();
|
|
|
|
drawing = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void gfx_lines_draw(float x0, float y0, float x1, float y1)
|
|
|
|
{
|
|
|
|
dbg_assert(drawing == DRAWING_LINES, "called draw without begin");
|
|
|
|
|
|
|
|
vertices[num_vertices].pos.x = x0;
|
|
|
|
vertices[num_vertices].pos.y = y0;
|
|
|
|
vertices[num_vertices].tex = texture[0];
|
|
|
|
vertices[num_vertices].color = color[0];
|
|
|
|
|
|
|
|
vertices[num_vertices + 1].pos.x = x1;
|
|
|
|
vertices[num_vertices + 1].pos.y = y1;
|
|
|
|
vertices[num_vertices + 1].tex = texture[1];
|
|
|
|
vertices[num_vertices + 1].color = color[1];
|
|
|
|
|
|
|
|
draw_line();
|
|
|
|
}
|