/* koyomi8.c - Don Yang (uguu.org) 09/30/09 */ #include #include #include #include #include #define _(Ko, yo, mi) Ko ## yo ## mi #define F for #define R return #define E else typedef double D; typedef int I; typedef unsigned char U; typedef void V; D CurrentTime, StartTime, EnvCloud[1025][1025], TaraiObject[7][3][8], top[3] = {107, 192, 229}, middle[3] = {240, 250, 250}, bottom[3] = {0, 128, 64}, t1 = .40, t2 = .39, dx, dy, r2, ly, ty, p; I CurrentFrame, TaraiObjectList, TextureObject, curve[9][4] = { {69, -27, 0, -1}, {75, -24, 3, -1}, {90, 21, 3, -1}, {93, 21, 0, -1}, {96, 24, 1, 0}, {93, 27, 0, 1}, {87, 27, -3, 1}, {72, -18, -3, 1}, {69, -21, 0, 1} }, i, j, x, y, cx, cy, nx, ny, const_list[] = { GL_TEXTURE_2D, GL_TEXTURE_GEN_S, GL_TEXTURE_GEN_T, GL_CULL_FACE, GL_DEPTH_TEST, GL_NORMALIZE, GL_S, GL_T, GL_TEXTURE_MAG_FILTER, GL_TEXTURE_MIN_FILTER, GL_LINEAR, GL_POLYGON, GL_RGB }; U TextureImage[512][512][3]; D ConvertRange(D sx, D input1, D sy, D output1, D value) { R (output1 - sy) * (value - sx) / (input1 - sx) + sy; } I ModulusRange(D value) { R ((i = (I)(512 * (value + 1))) < 0) ? 1024 - (1023 & -i) : i & 1023; } D RandomNumber(D sx, D sy) { R ConvertRange(0, RAND_MAX, sx, sy, rand()); } V SetCloudPixel(I sx, I sy, D value) { if( !j || (sx && sx - 1024 && sy && sy - 1024) ) EnvCloud[sy][sx] = value; } V SubDivideCloud(I sx, D sy) { F(; sx > 1; sy /= 2) { sx /= 2; F(y = 0; y < 1024; y = ny) { ny = (cy = y + sx) + sx; F(x = 0; x < 1024; x = nx) { nx = (cx = x + sx) + sx; SetCloudPixel(cx, cy, (EnvCloud[y][x] + EnvCloud[y][nx] + EnvCloud[ny][x] + EnvCloud[ny][nx]) / 4); SetCloudPixel(cx, y, (EnvCloud[y][x] + EnvCloud[y][nx] + EnvCloud[cy][cx]) / 3); SetCloudPixel(x, cy, (EnvCloud[y][x] + EnvCloud[cy][cx] + EnvCloud[ny][x]) / 3); SetCloudPixel(nx, cy, (EnvCloud[y][nx] + EnvCloud[cy][cx] + EnvCloud[ny][nx]) / 3); SetCloudPixel(cx, ny, (EnvCloud[cy][cx] + EnvCloud[ny][x] + EnvCloud[ny][nx]) / 3); SetCloudPixel(cx, y, EnvCloud[y][cx] + RandomNumber(-sy, sy)); SetCloudPixel(x, cy, EnvCloud[cy][x] + RandomNumber(-sy, sy)); SetCloudPixel(cx, cy, EnvCloud[cy][cx] + RandomNumber(-sy, sy)); SetCloudPixel(nx, cy, EnvCloud[cy][nx] + RandomNumber(-sy, sy)); SetCloudPixel(cx, ny, EnvCloud[ny][cx] + RandomNumber(-sy, sy)); } } } } V SetGradient(D *sx, D *sy, D value) { F(i = 0; i < 3; i++) TextureImage[y][x][i] = (U)ConvertRange(0, 1, sx[i], sy[i], value); } V SetTexturePixel(V) { if( ty > t1 ) { SetGradient(middle, top, ConvertRange(t1, 1, 0, 1, ty)); } E if( ty > t2 ) { F(i = 0; i < 3; i++) TextureImage[y][x][i] = (U)middle[i]; } E SetGradient(bottom, middle, ConvertRange(-1, t2, 0, 1, ty)); } V GenerateNewKeyframe(V) { F(j = 0; j < 8; j++) TaraiObject[i][0][j] = TaraiObject[i][1][j] = TaraiObject[i][2][j]; F(TaraiObject[i][1][6] += RandomNumber(2, 7); TaraiObject[i][2][7] == TaraiObject[i][0][7]; TaraiObject[i][2][7] = (I)RandomNumber(0, 4)); F(j = 0; j < 6; TaraiObject[i][1][j++] = RandomNumber(-360, 360)); j = (I)TaraiObject[i][2][7]; TaraiObject[i][1][j / 2] = ((j & 1) ? -360 : 360); } V UpdateClock(V) { struct timeval sx; gettimeofday(&sx, NULL); CurrentTime = sx.tv_sec + sx.tv_usec / 1e6; CurrentFrame++; } V Render(V) { UpdateClock(); glDrawBuffer(GL_BACK); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); x = glutGet(GLUT_WINDOW_WIDTH); y = glutGet(GLUT_WINDOW_HEIGHT); dx = dy = 1; if( x > y ) dx = x / (D)y; E dy = y / (D)x; glViewport(0, 0, x, y); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(-dx, dx, -dy, dy, 30, 1e6); gluLookAt(0, 0, -1e4, 0, 0, 0, 0, -1, 0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); F(i = 0; i < 7; i++) { F(j = 0; j < 6; j++) TaraiObject[i][2][j] = ConvertRange(TaraiObject[i][0][6], TaraiObject[i][1][6], TaraiObject[i][0][j], TaraiObject[i][1][j], CurrentTime); TaraiObject[i][2][6] = CurrentTime; if( CurrentTime >= TaraiObject[i][1][6] ) GenerateNewKeyframe(); glPushMatrix(); glTranslated(TaraiObject[i][2][0], TaraiObject[i][2][1], TaraiObject[i][2][2]); F(j = 3; j < 6; j++) glRotated(TaraiObject[i][2][j], (j - 3) ? 1 : 0, (j - 4) ? 1 : 0, (j - 5) ? 1 : 0); glCallList(TaraiObjectList); glPopMatrix(); } glutSwapBuffers(); glFlush(); } V Animate(V) { glutPostRedisplay(); } V Reshape(I sx, I y) { Animate(); } V Quit(U value, I sx, I sy) { glFlush(); if( (CurrentTime -= StartTime) > 1 ) printf("%ffps\n", CurrentFrame / CurrentTime); exit(0); } V Vertex(I sx) { glNormal3d(curve[sx][2] * cos(p), curve[sx][3], curve[sx][2] * sin(p)); glVertex3d(curve[sx][0] * cos(p), curve[sx][1], curve[sx][0] * sin(p)); } I main(I sx, char **sy) { glutInit(&sx, sy); glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH); glutSetWindow(glutCreateWindow("Koyomi")); glutDisplayFunc(Render); glutIdleFunc(Animate); glutReshapeFunc(Reshape); glutKeyboardFunc(Quit); glShadeModel(GL_SMOOTH); UpdateClock(); srand((I)CurrentTime); TaraiObjectList = glGenLists(1); glNewList(TaraiObjectList, GL_COMPILE); dx = atan2(0, -1) / 24; F(i = 0; i < 8; i++) { glBegin(GL_QUAD_STRIP); F(j = 0; j < 49;) { p = j++ * dx; Vertex(i); Vertex(i + 1); } glEnd(); } glBegin(const_list[11]); F(i = 0; i < 48; Vertex(0)) p = i++ * dx; glEnd(); glBegin(const_list[11]); F(i = y = 0; i < 48; Vertex(8)) p = i++ * -dx; glEnd(); sx = 1024; F(glEndList(); y <= sx; y += 128) F(x = i = j = 0; x <= sx; x += 128) EnvCloud[y][x] = 0; F(; i < 32; i++) EnvCloud[((I)RandomNumber(0, 8)) * 128] [((I)RandomNumber(0, 8)) * 128] = RandomNumber(.1, .3); SubDivideCloud(128, .06); F(i = 0; i <= sx; i++) { EnvCloud[sx][i] = EnvCloud[0][i]; EnvCloud[i][sx] = EnvCloud[i][0]; } j = 1; SubDivideCloud(sx, .48); F(y = 0; y < sx; y++) F(x = 0; x < sx; EnvCloud[y][x++] *= 255); sx /= 2; F(y = 0; y < sx; y++) { dy = ConvertRange(0, 511, 1, -1, y); F(x = 0; x < sx; x++) { dx = ConvertRange(0, 511, -1, 1, x); r2 = dx * dx + dy * dy; ly = sqrt((1 - dx * dx) / 2); if( dy >= ly ) { ty = 1; SetTexturePixel(); } E if( dy <= -ly ) { ty = -1; SetTexturePixel(); } E if( r2 < 1 ) { ty = dy / sqrt(1 - r2); if( ty >= -1 && ty <= 1 ) SetTexturePixel(); } if( r2 < 1 ) if( (p = EnvCloud[ModulusRange(dx / sqrt(1 - r2))] [ModulusRange(dy / sqrt(1 - r2))]) > 0 ) F(i = 0; i < 3; i++) TextureImage[y][x][i] = (U)((j = (I)TextureImage[y][x][i] + (I)p) > 255 ? 255 : j); } } glGenTextures(1, &TextureObject); glBindTexture(*const_list, TextureObject); F(i = 0; i < 6; glEnable(const_list[i++])); F(glTexImage2D(*const_list, 0, const_list[12], sx, sx, 0, const_list[12], GL_UNSIGNED_BYTE, TextureImage); i < 8; glTexGeni(const_list[i++], GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP)); F(glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); i < 10; glTexParameteri(*const_list, const_list[i++], const_list[10])); StartTime = CurrentTime; F(i = CurrentFrame = 0; i < 7; i++) { F(j = 0; j < 6; TaraiObject[i][2][j++] = RandomNumber(-360, 360)); TaraiObject[i][2][7] = TaraiObject[i][2][6] = CurrentTime; GenerateNewKeyframe(); } glutMainLoop(); R 0; }