273 lines
6.8 KiB
C
273 lines
6.8 KiB
C
|
#pragma warning(disable:4244; disable:4305; disable:4018)
|
||
|
#include <assert.h>
|
||
|
#include <ctype.h>
|
||
|
|
||
|
#define STB_DEFINE
|
||
|
#define STB_WINMAIN
|
||
|
#define STB_NO_REGISTRY
|
||
|
#include "stb_wingraph.h"
|
||
|
#include "stb.h"
|
||
|
|
||
|
#define STB_TRUETYPE_IMPLEMENTATION
|
||
|
#define STB_RECT_PACK_IMPLEMENTATION
|
||
|
#include "stb_rect_pack.h"
|
||
|
#include "stb_truetype.h"
|
||
|
|
||
|
#ifndef WINGDIAPI
|
||
|
#define CALLBACK __stdcall
|
||
|
#define WINGDIAPI __declspec(dllimport)
|
||
|
#define APIENTRY __stdcall
|
||
|
#endif
|
||
|
|
||
|
#include <gl/gl.h>
|
||
|
#include <gl/glu.h>
|
||
|
|
||
|
|
||
|
#define SIZE_X 1024
|
||
|
#define SIZE_Y 768
|
||
|
|
||
|
stbtt_packedchar chardata[3][128];
|
||
|
|
||
|
int sx=SIZE_X, sy=SIZE_Y;
|
||
|
|
||
|
#define BITMAP_W 512
|
||
|
#define BITMAP_H 512
|
||
|
unsigned char temp_bitmap[BITMAP_W][BITMAP_H];
|
||
|
unsigned char ttf_buffer[1 << 25];
|
||
|
GLuint font_tex;
|
||
|
|
||
|
void load_fonts(void)
|
||
|
{
|
||
|
stbtt_pack_context pc;
|
||
|
FILE *f = fopen("c:/windows/fonts/times.ttf", "rb");
|
||
|
if (!f) exit(0);
|
||
|
fread(ttf_buffer, 1, 1<<25, f);
|
||
|
|
||
|
stbtt_PackBegin(&pc, temp_bitmap[0], BITMAP_W, BITMAP_H, 0, 1, NULL);
|
||
|
stbtt_PackFontRange(&pc, ttf_buffer, 0, 24.0, 32, 95, chardata[0]+32);
|
||
|
stbtt_PackSetOversampling(&pc, 2, 2);
|
||
|
stbtt_PackFontRange(&pc, ttf_buffer, 0, 24.0, 32, 95, chardata[1]+32);
|
||
|
stbtt_PackSetOversampling(&pc, 3, 1);
|
||
|
stbtt_PackFontRange(&pc, ttf_buffer, 0, 24.0, 32, 95, chardata[2]+32);
|
||
|
stbtt_PackEnd(&pc);
|
||
|
|
||
|
glGenTextures(1, &font_tex);
|
||
|
glBindTexture(GL_TEXTURE_2D, font_tex);
|
||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, BITMAP_W, BITMAP_H, 0, GL_ALPHA, GL_UNSIGNED_BYTE, temp_bitmap);
|
||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||
|
}
|
||
|
|
||
|
void draw_init(void)
|
||
|
{
|
||
|
glDisable(GL_CULL_FACE);
|
||
|
glDisable(GL_TEXTURE_2D);
|
||
|
glDisable(GL_LIGHTING);
|
||
|
glDisable(GL_DEPTH_TEST);
|
||
|
|
||
|
glViewport(0,0,sx,sy);
|
||
|
glClearColor(0,0,0,0);
|
||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||
|
|
||
|
glMatrixMode(GL_PROJECTION);
|
||
|
glLoadIdentity();
|
||
|
gluOrtho2D(0,sx,sy,0);
|
||
|
glMatrixMode(GL_MODELVIEW);
|
||
|
glLoadIdentity();
|
||
|
}
|
||
|
|
||
|
|
||
|
void drawBoxTC(float x0, float y0, float x1, float y1, float s0, float t0, float s1, float t1)
|
||
|
{
|
||
|
glTexCoord2f(s0,t0); glVertex2f(x0,y0);
|
||
|
glTexCoord2f(s1,t0); glVertex2f(x1,y0);
|
||
|
glTexCoord2f(s1,t1); glVertex2f(x1,y1);
|
||
|
glTexCoord2f(s0,t1); glVertex2f(x0,y1);
|
||
|
}
|
||
|
|
||
|
int integer_align;
|
||
|
|
||
|
void print(float x, float y, int font, char *text)
|
||
|
{
|
||
|
glEnable(GL_TEXTURE_2D);
|
||
|
glBindTexture(GL_TEXTURE_2D, font_tex);
|
||
|
glBegin(GL_QUADS);
|
||
|
while (*text) {
|
||
|
stbtt_aligned_quad q;
|
||
|
stbtt_GetPackedQuad(chardata[font], BITMAP_W, BITMAP_H, *text++, &x, &y, &q, font ? 0 : integer_align);
|
||
|
drawBoxTC(q.x0,q.y0,q.x1,q.y1, q.s0,q.t0,q.s1,q.t1);
|
||
|
}
|
||
|
glEnd();
|
||
|
}
|
||
|
|
||
|
int font=0;
|
||
|
int translating;
|
||
|
int rotating=0;
|
||
|
float rotate_t, translate_t;
|
||
|
int show_tex;
|
||
|
|
||
|
void draw_world(void)
|
||
|
{
|
||
|
float x = 20;
|
||
|
glEnable(GL_BLEND);
|
||
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||
|
glColor3f(1,1,1);
|
||
|
|
||
|
if (font==1)
|
||
|
print(100, 50, font, "2x2 oversampled text at 1:1");
|
||
|
else if (font == 2)
|
||
|
print(100, 50, font, "3x1 oversampled text at 1:1");
|
||
|
else if (integer_align)
|
||
|
print(100, 50, font, "1:1 text, one texel = one pixel, snapped to integer coordinates");
|
||
|
else
|
||
|
print(100, 50, font, "1:1 text, one texel = one pixel");
|
||
|
|
||
|
print(100, 80, font, "O: toggle oversampling");
|
||
|
print(100,105, font, "T: toggle translation");
|
||
|
print(100,130, font, "R: toggle rotation");
|
||
|
print(100,155, font, "P: toggle pixel-snap (only non-oversampled)");
|
||
|
print(100,180, font, "V: view font texture");
|
||
|
|
||
|
if (show_tex) {
|
||
|
glBegin(GL_QUADS);
|
||
|
drawBoxTC(200,200, 200+BITMAP_W,200+BITMAP_H, 0,0,1,1);
|
||
|
glEnd();
|
||
|
} else {
|
||
|
glMatrixMode(GL_MODELVIEW);
|
||
|
glTranslatef(200,250,0);
|
||
|
|
||
|
if (translating)
|
||
|
x += fmod(translate_t*8,30);
|
||
|
|
||
|
if (rotating) {
|
||
|
glTranslatef(100,150,0);
|
||
|
glRotatef(rotate_t*2,0,0,1);
|
||
|
glTranslatef(-100,-150,0);
|
||
|
}
|
||
|
print(x,100, font, "This is a test");
|
||
|
print(x,130, font, "Now is the time for all good men to come to the aid of their country.");
|
||
|
print(x,160, font, "The quick brown fox jumps over the lazy dog.");
|
||
|
print(x,190, font, "0123456789");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void draw(void)
|
||
|
{
|
||
|
draw_init();
|
||
|
draw_world();
|
||
|
stbwingraph_SwapBuffers(NULL);
|
||
|
}
|
||
|
|
||
|
static int initialized=0;
|
||
|
static float last_dt;
|
||
|
|
||
|
int move[4];
|
||
|
int raw_mouse_x, raw_mouse_y;
|
||
|
|
||
|
int loopmode(float dt, int real, int in_client)
|
||
|
{
|
||
|
float actual_dt = dt;
|
||
|
|
||
|
if (!initialized) return 0;
|
||
|
|
||
|
rotate_t += dt;
|
||
|
translate_t += dt;
|
||
|
|
||
|
// music_sim();
|
||
|
if (!real)
|
||
|
return 0;
|
||
|
|
||
|
if (dt > 0.25) dt = 0.25;
|
||
|
if (dt < 0.01) dt = 0.01;
|
||
|
|
||
|
draw();
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int winproc(void *data, stbwingraph_event *e)
|
||
|
{
|
||
|
switch (e->type) {
|
||
|
case STBWGE_create:
|
||
|
break;
|
||
|
|
||
|
case STBWGE_char:
|
||
|
switch(e->key) {
|
||
|
case 27:
|
||
|
stbwingraph_ShowCursor(NULL,1);
|
||
|
return STBWINGRAPH_winproc_exit;
|
||
|
break;
|
||
|
case 'o': case 'O':
|
||
|
font = (font+1) % 3;
|
||
|
break;
|
||
|
case 't': case 'T':
|
||
|
translating = !translating;
|
||
|
translate_t = 0;
|
||
|
break;
|
||
|
case 'r': case 'R':
|
||
|
rotating = !rotating;
|
||
|
rotate_t = 0;
|
||
|
break;
|
||
|
case 'p': case 'P':
|
||
|
integer_align = !integer_align;
|
||
|
break;
|
||
|
case 'v': case 'V':
|
||
|
show_tex = !show_tex;
|
||
|
break;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case STBWGE_mousemove:
|
||
|
raw_mouse_x = e->mx;
|
||
|
raw_mouse_y = e->my;
|
||
|
break;
|
||
|
|
||
|
#if 0
|
||
|
case STBWGE_mousewheel: do_mouse(e,0,0); break;
|
||
|
case STBWGE_leftdown: do_mouse(e, 1,0); break;
|
||
|
case STBWGE_leftup: do_mouse(e,-1,0); break;
|
||
|
case STBWGE_rightdown: do_mouse(e,0, 1); break;
|
||
|
case STBWGE_rightup: do_mouse(e,0,-1); break;
|
||
|
#endif
|
||
|
|
||
|
case STBWGE_keydown:
|
||
|
if (e->key == VK_RIGHT) move[0] = 1;
|
||
|
if (e->key == VK_LEFT) move[1] = 1;
|
||
|
if (e->key == VK_UP) move[2] = 1;
|
||
|
if (e->key == VK_DOWN) move[3] = 1;
|
||
|
break;
|
||
|
case STBWGE_keyup:
|
||
|
if (e->key == VK_RIGHT) move[0] = 0;
|
||
|
if (e->key == VK_LEFT) move[1] = 0;
|
||
|
if (e->key == VK_UP) move[2] = 0;
|
||
|
if (e->key == VK_DOWN) move[3] = 0;
|
||
|
break;
|
||
|
|
||
|
case STBWGE_size:
|
||
|
sx = e->width;
|
||
|
sy = e->height;
|
||
|
loopmode(0,1,0);
|
||
|
break;
|
||
|
|
||
|
case STBWGE_draw:
|
||
|
if (initialized)
|
||
|
loopmode(0,1,0);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
return STBWINGRAPH_unprocessed;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
void stbwingraph_main(void)
|
||
|
{
|
||
|
stbwingraph_Priority(2);
|
||
|
stbwingraph_CreateWindow(1, winproc, NULL, "tt", SIZE_X,SIZE_Y, 0, 1, 0, 0);
|
||
|
stbwingraph_ShowCursor(NULL, 0);
|
||
|
load_fonts();
|
||
|
initialized = 1;
|
||
|
stbwingraph_MainLoop(loopmode, 0.016f); // 30 fps = 0.33
|
||
|
}
|
||
|
|