/* aya6.c - Don Yang (uguu.org) 10/04/06 */ #include #include #include #include #include #include double PI, ColorCurveR[] = { .9, .98, 1, 0, -1 }, ColorCurveGB[] = { .32, .98, .36, .12, .54, .12, .58, .98, .9, .98, 1, 0, -1 }, ColorCurveA[] = { .56, .99, .58, .7, .9, 0, -1 }, CurrentTime, x, y, r, ix0, iy0, ix1, iy1; struct { double t0, x, y, r0, r1; } GlobalEmitter; int i, j, k, TextureHandle, SpriteHandle; unsigned char TextureImage[16384], *p; double RandomRange(double u, double v) { return u + (v - u) * (rand() & 0x3fff) / 16383.; } void UpdateClock(void) { struct timeval t; gettimeofday(&t, NULL); CurrentTime = t.tv_sec + t.tv_usec / 1e6; } void Render(void) { UpdateClock(); glDrawBuffer(GL_BACK); glClear(GL_COLOR_BUFFER_BIT); glViewport(0, 0, i = glutGet(GLUT_WINDOW_WIDTH), j = glutGet(GLUT_WINDOW_HEIGHT)); glMatrixMode(GL_PROJECTION); glLoadIdentity(); if( i > j ) gluOrtho2D(-i / (double)j, i / (double)j, -1, 1); else gluOrtho2D(-1, 1, -j / (double)i, j / (double)i); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); ix0 = (CurrentTime - GlobalEmitter.t0) / 1.5; for(i = 0; i < 23; i++) { ix1 = ix0 - i / 23.; if( ix1 < 0 ) continue; r = ix1 * 2.1; for(j = 0; j < 32; j++) { x = GlobalEmitter.r0 + j * PI / 16.; y = GlobalEmitter.r1 + j * PI / 16.; iy1 = ix1 * (y - x) + x; if( i & 1 ) iy1 += PI / 32; x = r * cos(iy1) + GlobalEmitter.x; y = r * sin(iy1) + GlobalEmitter.y; glPushMatrix(); glTranslated(x, y, 0); glCallList(SpriteHandle); glPopMatrix(); } } if( ix0 > 2.2 ) { GlobalEmitter.t0 = CurrentTime; GlobalEmitter.r0 = GlobalEmitter.r1 = RandomRange(0, PI * 2); if( !(rand() & 3) ) GlobalEmitter.r1 += RandomRange(-PI / 3, PI / 3); GlobalEmitter.x = RandomRange(-.5, .5); GlobalEmitter.y = RandomRange(-.5, .5); } glutSwapBuffers(); glFlush(); } void RenderFirstFrame(void) { UpdateClock(); srand((unsigned int)CurrentTime); glGenTextures(1, &TextureHandle); glBindTexture(GL_TEXTURE_2D, TextureHandle); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)TextureImage); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glEnable(GL_BLEND); glEnable(GL_TEXTURE_2D); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glNewList(SpriteHandle = glGenLists(1), GL_COMPILE); glBegin(GL_TRIANGLE_FAN); glTexCoord2d(0, 0); glVertex2d(-.07, -.07); glTexCoord2d(1, 0); glVertex2d( .07, -.07); glTexCoord2d(1, 1); glVertex2d( .07, .07); glTexCoord2d(0, 1); glVertex2d(-.07, .07); glEnd(); glEndList(); GlobalEmitter.t0 = CurrentTime; GlobalEmitter.x = GlobalEmitter.y = GlobalEmitter.r0 = GlobalEmitter.r1 = 0; glutDisplayFunc(Render); Render(); } void Animate(void) { glutPostRedisplay(); } void Reshape(int w, int h) { glutPostRedisplay(); } void Quit(unsigned char c, int u, int v) { glFlush(); glDeleteLists(SpriteHandle, 1); glDeleteTextures(1, &TextureHandle); exit(0); } double StepFunc(double t, double *curve) { ix0 = *curve++; iy0 = *curve++; if( t < ix0 ) return iy0; for(;;) { ix1 = *curve++; if( ix1 < ix0 ) break; iy1 = *curve++; if( t < ix1 ) return (iy1 - iy0) * (t - ix0) / (ix1 - ix0) + iy0; ix0 = ix1; iy0 = iy1; } return iy0; } int main(int argc, char **argv) { glutInit(&argc, argv); PI = atan2(0, -1); p = memset(TextureImage, 0, 16384); for(i = 0; i < 64; i++) { x = i / 32. - 1; for(j = 0; j < 64; j++) { y = j / 32. - 1; r = sqrt(x * x + y * y); k = 255 * StepFunc(r, ColorCurveR); if( k > 255 ) k = 255; *p++ = k; k = 255 * StepFunc(r, ColorCurveGB); if( k > 255 ) k = 255; *p++ = k; *p++ = k; k = 255 * StepFunc(r, ColorCurveA); if( k > 255 ) k = 255; *p++ = k; } } glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE); glutSetWindow(glutCreateWindow("Aya")); glutDisplayFunc(RenderFirstFrame); glutIdleFunc(Animate); glutReshapeFunc(Reshape); glutKeyboardFunc(Quit); glutMainLoop(); return 0; }