/* #include <GL/freeglut.h> */
#include <GL/glut.h>
#include <math.h>
#ifndef M_PI
# define M_PI (3.141592653589793)
#endif
#define ROTATION_RADIAN (M_PI/6.0)
#define RATIO_EXPANSION (1.6)
#define RATIO_SHRINK (0.6)
#define VERTEX_NUM (10)
#define BLUR_NUM (2)
static double g_matrix[BLUR_NUM][2][3];
static double g_object[VERTEX_NUM][2];
static int g_current;
static void makeStar(double vertex[][2], int nv, double r0, double r1);
static void initMatrix(double matrix[2][3]);
static void makeTranslationMatrix(double matrix[2][3], const double tx, const double ty);
static void makeRotationMatrix(double matrix[2][3], const double r);
static void makeScaleMatrix(double matrix[2][3], const double sx, const double sy);
static void makeTransformationMatrix(double matrix[2][3], const double lhs[2][3], const double rhs[2][3]);
static void transform(double vertex[][2], int nv, const double matrix[2][3], const double input[][2]);
static void display(void);
static void key(unsigned char key , int x , int y);
static void init(void);
void makeStar(double vertex[][2], int nv, double r0, double r1)
{
int i;
for (i = 0; i < nv / 2; ++i) {
vertex[2*i+0][0] = cos(M_PI/2.0 + 2.0*M_PI / nv * (2*i+0)) * r0;
vertex[2*i+0][1] = sin(M_PI/2.0 + 2.0*M_PI / nv * (2*i+0)) * r0;
vertex[2*i+1][0] = cos(M_PI/2.0 + 2.0*M_PI / nv * (2*i+1)) * r1;
vertex[2*i+1][1] = sin(M_PI/2.0 + 2.0*M_PI / nv * (2*i+1)) * r1;
}
}
void initMatrix(double m[2][3])
{
m[0][0] = 1.0; m[0][1] = 0.0; m[0][2] = 0.0;
m[1][0] = 0.0; m[1][1] = 1.0; m[1][2] = 0.0;
}
void makeTranslationMatrix(double matrix[2][3], const double tx, const double ty)
{
matrix[0][0] = 1.0; matrix[0][1] = 0.0; matrix[0][2] = tx;
matrix[1][0] = 0.0; matrix[1][1] = 1.0; matrix[1][2] = ty;
}
void makeRotationMatrix(double matrix[2][3], const double r)
{
double c, s;
c = cos(r);
s = sin(r);
matrix[0][0] = c; matrix[0][1] = -s; matrix[0][2] = 0.0;
matrix[1][0] = s; matrix[1][1] = c; matrix[1][2] = 0.0;
}
void makeScaleMatrix(double matrix[2][3], const double sx, const double sy)
{
matrix[0][0] = sx; matrix[0][1] = 0.0; matrix[0][2] = 0.0;
matrix[1][0] = 0.0; matrix[1][1] = sy; matrix[1][2] = 0.0;
}
void makeTransformationMatrix(double matrix[2][3], const double l[2][3], const double r[2][3])
{
matrix[0][0] = l[0][0]*r[0][0] + l[0][1]*r[1][0];
matrix[0][1] = l[0][0]*r[0][1] + l[0][1]*r[1][1];
matrix[0][2] = l[0][0]*r[0][2] + l[0][1]*r[1][2] + l[0][2];
matrix[1][0] = l[1][0]*r[0][0] + l[1][1]*r[1][0];
matrix[1][1] = l[1][0]*r[0][1] + l[1][1]*r[1][1];
matrix[1][2] = l[1][0]*r[0][2] + l[1][1]*r[1][2] + l[1][2];
}
void transform(double vertex[][2], int nv, const double matrix[2][3], const double input[][2])
{
int i;
for (i = 0; i < nv; ++i) {
vertex[i][0] = matrix[0][0]*input[i][0] + matrix[0][1]*input[i][1] + matrix[0][2];
vertex[i][1] = matrix[1][0]*input[i][0] + matrix[1][1]*input[i][1] + matrix[1][2];
}
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
/* Axis */
glBegin(GL_LINES); {
glColor3f(1.0, 1.0, 1.0);
/* X */
glVertex2d(-1.0, 0.0);
glVertex2d(1.0, 0.0);
/* Y */
glVertex2d(0.0, -1.0);
glVertex2d(0.0, 1.0);
} glEnd();
/* Object */
{
double vertex[VERTEX_NUM][2];
glColor3f(0.0f, 1.0f, 0.0f);
transform(vertex, VERTEX_NUM, g_matrix[g_current], g_object);
glBegin(GL_LINE_LOOP); {
int i;
for(i = 0; i < VERTEX_NUM; ++i) {
glVertex2d(vertex[i][0], vertex[i][1]);
}
}
glEnd();
}
glFlush();
}
void key(unsigned char key , int x , int y) {
switch (key) {
case '\033': /* Key ESC */
glutLeaveMainLoop();
break;
case 'a': { /* -X */
double m[2][3];
int p = g_current;
if (BLUR_NUM <= ++g_current) { g_current = 0; }
makeTranslationMatrix(m, -0.1, 0.0);
makeTransformationMatrix(g_matrix[g_current], m, g_matrix[p]);
break;
}
case 'd': { /* +X */
double m[2][3];
int p = g_current;
if (BLUR_NUM <= ++g_current) { g_current = 0; }
makeTranslationMatrix(m, 0.1, 0.0);
makeTransformationMatrix(g_matrix[g_current], m, g_matrix[p]);
break;
}
case 'w': { /* +Y */
double m[2][3];
int p = g_current;
if (BLUR_NUM <= ++g_current) { g_current = 0; }
makeTranslationMatrix(m, 0.0, 0.1);
makeTransformationMatrix(g_matrix[g_current], m, g_matrix[p]);
break;
}
case 's': { /* -Y */
double m[2][3];
int p = g_current;
if (BLUR_NUM <= ++g_current) { g_current = 0; }
makeTranslationMatrix(m, 0.0, -0.1);
makeTransformationMatrix(g_matrix[g_current], m, g_matrix[p]);
break;
}
case 'j': { /* counterclockwise local */
double m[2][3];
int p = g_current;
if (BLUR_NUM <= ++g_current) { g_current = 0; }
makeRotationMatrix(m, ROTATION_RADIAN);
makeTransformationMatrix(g_matrix[g_current], g_matrix[p], m);
break;
}
case 'J': { /* clockwise local */
double m[2][3];
int p = g_current;
if (BLUR_NUM <= ++g_current) { g_current = 0; }
makeRotationMatrix(m, -ROTATION_RADIAN);
makeTransformationMatrix(g_matrix[g_current], g_matrix[p], m);
break;
}
case 'r': /* reset */
init();
break;
default:
break;
}
glutPostRedisplay();
}
void init(void)
{
int i;
for (i = 0; i < BLUR_NUM; ++i) {
initMatrix(g_matrix[i]);
}
makeStar(g_object, VERTEX_NUM, 0.5, 0.25);
g_current = 0;
}
int main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA);
glutCreateWindow(argv[0]);
glutDisplayFunc(display);
glutKeyboardFunc(key);
glClearColor(0.0, 0.0, 0.0, 0.0);
init();
glutMainLoop();
return 0;
}