//
// OpenGL example showing text on a rotating 3D object.
// erco 03/03/06
//
#include <FL/Fl.H>
#include <FL/Fl_Gl_Window.H>
#include <FL/gl.h>
#include <GL/glu.h>
#include <string.h>
#include <stdio.h>
// These strings are from the Wikipedia page on Japanese
// under the "Book of Song" heading.
//
const char *songnames[] = { // (Following comments look right in a UTF8 editor)
"1: \xe9\xa0\x86\xe5\xb8\x9d\xe6\x98\x87\xe6\x98\x8e" // 順帝昇明二年
"\xe4\xba\x8c\xe5\xb9\xb4",
"2: \xe9\x81\xa3\xe4\xbd\xbf\xe4\xb8\x8a\xe8\xa1\xa8" // 遣使上表曰
"\xe6\x9b\xb0",
"3: \xe4\xbd\x9c\xe8\x97\xa9\xe4\xba\x8e\xe5\xa4\x96", // 作藩于外
"4: \xe8\x87\xaa\xe6\x98\x94\xe7\xa5\x96\xe7\xa6\xb0", // 自昔祖禰
"5: \xe8\xba\xac\xe6\x93\x90\xe7\x94\xb2\xe5\x86\x91", // 躬擐甲冑
"6: \xe8\xb7\x8b\xe6\xb8\x89\xe5\xb1\xb1\xe5\xb7\x9d", // 跋渉山川
"7: \xe4\xb8\x8d\xe9\x81\x91\xe5\xaf\xa7\xe8\x99\x95" // 不遑寧處。東征毛人五十國
"\xe3\x80\x82\xe6\x9d\xb1\xe5\xbe\x81\xe6\xaf\x9b"
"\xe4\xba\xba\xe4\xba\x94\xe5\x8d\x81\xe5\x9c\x8b",
"8: \xe8\xa5\xbf\xe6\x9c\x8d\xe8\xa1\x86\xe5\xa4\xb7" // etc..
"\xe5\x85\xad\xe5\x8d\x81\xe5\x85\xad\xe5\x9c\x8b",
"9: \xe6\xb8\xa1\xe5\xb9\xb3\xe6\xb5\xb7\xe5\x8c\x97"
"\xe4\xb9\x9d\xe5\x8d\x81\xe4\xba\x94\xe5\x9c\x8b",
"10: \xe7\x8e\x8b\xe9\x81\x93\xe8\x9e\x8d\xe6\xb3\xb0",
"11: \xe5\xbb\x93\xe5\x9c\x9f\xe9\x81\x90\xe7\x95\xbf",
"12: \xe7\xb4\xaf\xe8\x91\x89\xe6\x9c\x9d\xe5\xae\x97",
"13: \xe4\xb8\x8d\xe6\x84\x86\xe4\xba\x8e\xe6\xad\xb3"
"\xe3\x80\x82\xe8\x87\xa3\xe9\x9b\x96\xe4\xb8\x8b"
"\xe6\x84\x9a",
"14: \xe5\xbf\x9d\xe8\x83\xa4\xe5\x85\x88\xe7\xb7\x92",
"15: \xe9\xa9\x85\xe7\x8e\x87\xe6\x89\x80\xe7\xb5\xb1",
"16: \xe6\xad\xb8\xe5\xb4\x87\xe5\xa4\xa9\xe6\xa5\xb5",
0
};
// Tetrahedron points
#define TOP 0, 1, 0
#define RIGHT 1, -1, 1
#define LEFT -1, -1, 1
#define BACK 0, -1, -1
class MyGlWindow : public Fl_Gl_Window {
float rotangle;
void draw() {
// First time? init viewport, etc.
if (!valid()) {
valid(1);
// Initialize GL
glClearColor(0.0, 0.0, 0.0, 0.0);
glClearDepth(1.0);
glDepthFunc(GL_LESS);
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_FLAT);
}
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
// Position camera/viewport init
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glViewport(0,0,w(),h());
gluPerspective(45.0, (float)w()/(float)h(), 1.0, 10.0);
glTranslatef(0.0, 0.0, -5.0);
// Position object
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef(rotangle, 1, 0, 1);
glRotatef(rotangle, 0, 1, 0);
glRotatef(rotangle, 1, 1, 1);
// Draw tetrahedron
glColor3f(1.0, 0.0, 0.0); glBegin(GL_POLYGON); glVertex3f(TOP); glVertex3f(RIGHT); glVertex3f(LEFT); glEnd();
glColor3f(0.0, 1.0, 0.0); glBegin(GL_POLYGON); glVertex3f(TOP); glVertex3f(BACK); glVertex3f(RIGHT); glEnd();
glColor3f(0.0, 0.0, 1.0); glBegin(GL_POLYGON); glVertex3f(TOP); glVertex3f(LEFT); glVertex3f(BACK); glEnd();
glColor3f(0.5, 0.5, 0.5); glBegin(GL_POLYGON); glVertex3f(RIGHT); glVertex3f(BACK); glVertex3f(LEFT); glEnd();
// Print tetrahedron's points on object
// Disable depth buffer while drawing text,
// so text draws /over/ object.
//
glDisable(GL_DEPTH_TEST);
{
const char *p;
gl_font(FL_HELVETICA, 15);
glColor3f(1.0, 1.0, 1.0);
glRasterPos3f(TOP); p = songnames[0]; gl_draw(p, strlen(p));
glRasterPos3f(LEFT); p = songnames[1]; gl_draw(p, strlen(p));
glRasterPos3f(RIGHT); p = songnames[2]; gl_draw(p, strlen(p));
glRasterPos3f(BACK); p = songnames[3]; gl_draw(p, strlen(p));
}
glEnable(GL_DEPTH_TEST);
// Print rotangle value at fixed position at lower left
char s[40];
sprintf(s, "ROT=%.2f", rotangle);
glLoadIdentity(); glRasterPos2f(-3,-2); gl_draw(s, strlen(s));
}
static void Timer_CB(void *userdata) {
MyGlWindow *o = (MyGlWindow*)userdata;
o->rotangle += 1.0;
o->redraw();
Fl::repeat_timeout(1.0/24.0, Timer_CB, userdata); // 24fps
}
public:
// CONSTRUCTOR
MyGlWindow(int X,int Y,int W,int H,const char*L=0) : Fl_Gl_Window(X,Y,W,H,L) {
rotangle = 0;
Fl::add_timeout(3.0, Timer_CB, (void*)this); // wait 3 secs before animation begins
}
};
// MAIN
int main() {
Fl_Window win(500, 300);
MyGlWindow mygl(10, 10, win.w()-20, win.h()-20);
win.show();
return(Fl::run());
}
// end of file //