/* aya5.c - Don Yang (uguu.org) 10/04/06 */ #include #include #include #include #include #include double PI, ColorCurveR[] = { 0.9, 0.98, 1.0, 0.0, -1.0 }, ColorCurveGB[] = { 0.32, 0.98, 0.36, 0.12, 0.54, 0.12, 0.58, 0.98, 0.9, 0.98, 1.0, 0.0, -1.0 }, ColorCurveA[] = { 0.56, 0.99, 0.58, 0.70, 0.9, 0.0, -1.0 }, CurrentTime, x, y, r, c, ix0, iy0, ix1, iy1; struct { double t0, x, y, r0, r1; } GlobalEmitter; int i, j, k, TextureHandle, SpriteHandle; unsigned char TextureImage[64 * 64 * 4], *p; double RandomRange(double u, double v) { return u + (v - u) * (rand() & 0x3fff) / 16383.0; } void UpdateClock(void) { struct timeval t; gettimeofday(&t, NULL); CurrentTime = (double)t.tv_sec + (double)(t.tv_usec / 1000000.0); } void Render(void) { UpdateClock(); glDrawBuffer(GL_BACK); glClear(GL_COLOR_BUFFER_BIT); i = glutGet(GLUT_WINDOW_WIDTH); j = glutGet(GLUT_WINDOW_HEIGHT); glViewport(0, 0, i, j); glMatrixMode(GL_PROJECTION); glLoadIdentity(); if( i > j ) gluOrtho2D(-i / j, i / j, -1.0, 1.0); else gluOrtho2D(-1.0, 1.0, -j / i, j / i); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); ix0 = (CurrentTime - GlobalEmitter.t0) / 1.5; for(i = 0; i < 23; i++) { ix1 = ix0 - (i / 23.0); if( ix1 < 0.0 ) continue; r = ix1 * 2.1; for(j = 0; j < 32; j++) { x = GlobalEmitter.r0 + j * PI * 2.0 / 32.0; y = GlobalEmitter.r1 + j * PI * 2.0 / 32.0; iy1 = ix1 * (y - x) + x; if( (i & 1) != 0 ) iy1 += PI * 2.0 / 64.0; x = r * cos(iy1) + GlobalEmitter.x; y = r * sin(iy1) + GlobalEmitter.y; glPushMatrix(); glTranslated(x, y, 0.0); glCallList(SpriteHandle); glPopMatrix(); } } if( ix0 > 2.2 ) { GlobalEmitter.t0 = CurrentTime; GlobalEmitter.r0 = GlobalEmitter.r1 = RandomRange(0.0, PI * 2.0); if( (rand() & 3) == 0 ) GlobalEmitter.r1 += RandomRange(-PI / 3.0, PI / 3.0); GlobalEmitter.x = RandomRange(-0.5, 0.5); GlobalEmitter.y = RandomRange(-0.5, 0.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, 0.0); glVertex2d(-0.07, -0.07); glTexCoord2d(1.0, 0.0); glVertex2d( 0.07, -0.07); glTexCoord2d(1.0, 1.0); glVertex2d( 0.07, 0.07); glTexCoord2d(0.0, 1.0); glVertex2d(-0.07, 0.07); glEnd(); glEndList(); GlobalEmitter.t0 = CurrentTime; GlobalEmitter.x = GlobalEmitter.y = GlobalEmitter.r0 = GlobalEmitter.r1 = 0.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(EXIT_SUCCESS); } 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.0, -1.0); p = memset(TextureImage, 0, 64 * 64 * 4); for(i = 0; i < 64; i++) { x = ((double)i - (64 / 2)) / (64 / 2); for(j = 0; j < 64; j++) { y = ((double)j - (64 / 2)) / (64 / 2); r = sqrt(x * x + y * y); c = StepFunc(r, ColorCurveR); k = (int)(255 * c); if( k > 255 ) k = 255; *(p++) = (unsigned char)k; c = StepFunc(r, ColorCurveGB); k = (int)(255 * c); if( k > 255 ) k = 255; *(p++) = (unsigned char)k; *(p++) = (unsigned char)k; c = StepFunc(r, ColorCurveA); k = (int)(255 * c); if( k > 255 ) k = 255; *(p++) = (unsigned char)k; } } glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE); glutSetWindow(glutCreateWindow("Aya")); glutDisplayFunc(RenderFirstFrame); glutIdleFunc(Animate); glutReshapeFunc(Reshape); glutKeyboardFunc(Quit); glutMainLoop(); return 0; }