#include #include #include #include #include #include #include #include #include "SDL.h" #include "SDL_image.h" #include "SDL_opengl.h" SDL_Surface *screen; const unsigned int width = 640, height = 480; class Drawer { private: float fMinX; float fMinY; float fHeight; float fWidth; float fDistX; float fDistY; int iScreenHeight; int iScreenWidth; int iOriginX; int iOriginY; float iScale; float jScale; std::vector distances; std::vector previousGrid; std::vector currentGrid; std::vector grid; std::vector vertices; std::vector colors; int currentT; public: //Constructor Drawer(float fScreeMaxX,float fScreenMaxY,float fScreenMinX,float fScreenMinY, int iScreenX,int iScreenY,int iCenterX,int iCenterY); //Formulas inline float Wrangle(float distance,float fT); //Drawers void Draw(float iT); }; static const float fRadian = 3.14159265f / 180.0f; Drawer::Drawer(float fScreenMaxX,float fScreenMaxY,float fScreenMinX,float fScreenMinY,int iScreenX, int iScreenY,int iCenterX,int iCenterY) : distances(iScreenX * iScreenY) , previousGrid(iScreenX * iScreenY) , currentGrid(iScreenX * iScreenY) , grid(iScreenX * iScreenY) , vertices((iScreenX - 1) * iScreenY * 6) , colors((iScreenX - 1) * iScreenY * 6) , currentT(0) { fMinX = fScreenMinX; fMinY = fScreenMinY; fHeight = fScreenMaxY - fScreenMinY; fWidth = fScreenMaxX - fScreenMinX; fDistX = fWidth/iScreenX; fDistY = fHeight/iScreenY; iScreenHeight = iScreenX; iScreenWidth = iScreenY; iOriginX = iCenterX; iOriginY = iCenterX; iScale = 64./iScreenWidth; jScale = 64./iScreenHeight; for (int i = 0; i < iScreenHeight; ++i) { for (int j = 0; j < iScreenWidth; ++j) { float fX = (i*iScale - iOriginX) * 100 * fRadian; float fY = (j*jScale - iOriginY) * 100 * fRadian; distances[i * iScreenWidth + j] = sqrt(fX*fX + fY*fY); } } } float Drawer::Wrangle(float fDistance, float fT) { fT *= 5*fRadian; float fCircular = cos( fDistance-fT)*0.025; float fDamp = fDistance*0.025; if(fDamp < 0.5f) fDamp = 0.5f; return fCircular/fDamp; } void Rand(int iT,int iHeight,int iWidth,std::vector & fGrid,int iCenterX,int iCenterY) { static int iRand[32]; static int iCoolDown = 0; if (!iT) { int k = 0; while(k < 32) iRand[k++] = rand()%4; } int iIterator; //int k = 0; if(!iCoolDown) { int iTemp = rand()%16; iRand[iTemp] = rand()%4; //iRand[k+1] = iT; if(iTemp < 4) iCoolDown = 96; } else { iRand[16 + (iCoolDown%16)-8] = rand()%4; iCoolDown--; } for (int i = 0; i < iHeight; i++) { for (int j = 0; j < iWidth; j++) { float fX = (float)(i-iCenterX)/(float)(iHeight); float fY = (float)(j-iCenterY)/(float)(iWidth); iIterator = 0; while( fX < 4 && fY < 4) { if(iRand[iIterator] == 0) { float fTemp = fX; fX = fY/2; fY = fTemp*2; } else if(iRand[iIterator] == 1) { float fTemp = fY; fY = cos(fX); fX = cos(fTemp); } else if(iRand[iIterator] == 2) { fX = fX*fX; fY = 1./fY; } else if(iRand[iIterator] == 3) { float fTemp = fY; fY = (fY-fX) * fY; fX = (fX-fTemp) * fX; } if(iIterator >= 32) break; iIterator++; } fGrid[i * iWidth + j] = 0.0625 + (float)(iIterator-32)/128.0f; } } } inline float lerp(float t, float x1, float x2) { return (1 - t) * x1 + t * x2; } void Drawer::Draw(float iT) { int i = 0; glColor3f(0.0f,0.0f,1.0f); #if 0 for (int i = 0; i < iScreenHeight; ++i) for (int j = 0; j < iScreenWidth; ++j) grid[i * iScreenWidth + j] = Wrangle(distances[i * iScreenWidth + j], iT); #else if (iT > currentT + 1) { currentT = int(iT); swap(previousGrid, currentGrid); Rand(currentT, iScreenHeight, iScreenWidth, currentGrid, iOriginX, iOriginY); } float t = iT - currentT; for (int i = 0; i < iScreenHeight; ++i) { for (int j = 0; j < iScreenWidth; ++j) { int index = i * iScreenWidth + j; grid[index] = lerp(t, previousGrid[index], currentGrid[index]); } } #endif while(i < iScreenHeight - 1) { float fResult[2]; int j = 0; while(j < iScreenWidth) { fResult[0] = grid[(i + 1) * iScreenWidth + j]; fResult[1] = grid[i * iScreenWidth + j]; int index = (i*iScreenWidth+j)*6; colors[index + 2] = 0.75 - fResult[0]*10; colors[index + 5] = 0.75 - fResult[1]*10; float fX = fMinX + i*fDistX; float fY = fMinY + j*fDistY; vertices[index] = fX + fDistX; vertices[index+1] = fY; vertices[index+2] = fResult[0]; vertices[index+3] = fX; vertices[index+4] = fY; vertices[index+5] = fResult[1]; j++; } i++; } glVertexPointer(3, GL_FLOAT, 0, &vertices[0]); glColorPointer(3, GL_FLOAT, 0, &colors[0]); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_COLOR_ARRAY); for (int i = 0; i < iScreenHeight-1; ++i) glDrawArrays(GL_TRIANGLE_STRIP, iScreenWidth*i*2, iScreenWidth*2); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_COLOR_ARRAY); } void render(float time, Drawer &Simple) { if (SDL_MUSTLOCK(screen)) if (SDL_LockSurface(screen) < 0) return; glClearColor (0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT); glPushMatrix(); glRotatef(45.0f, 1.0f, 1.0f, 0.0f); Simple.Draw(time * 20); glPopMatrix(); if (SDL_MUSTLOCK(screen)) SDL_UnlockSurface(screen); //SDL_UpdateRect(screen, 0, 0, width, height); SDL_GL_SwapBuffers(); } int main(int argc, char *argv[]) { printf("%s\n", argv[0]); if (SDL_Init(SDL_INIT_VIDEO) < 0) std::exit(1); atexit(SDL_Quit); SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16); screen = SDL_SetVideoMode(width, height, 0, SDL_OPENGL); if (!screen) std::exit(1); glClearColor(0.0, 0.0, 0.0, 0.0); unsigned int lastTime = SDL_GetTicks(); float accumulatedSeconds = 0; int frames = 0; bool done = false; Drawer Simple(0.9f,0.9f,-0.9f,-0.9f,128,128,-32,-32); while (!done) { unsigned int currentTime = SDL_GetTicks(); while (currentTime == lastTime) currentTime = SDL_GetTicks(); float seconds = (currentTime - lastTime) * 0.001f; accumulatedSeconds += seconds; render(accumulatedSeconds, Simple); lastTime = currentTime; ++frames; SDL_Event event; while (SDL_PollEvent(&event)) { switch (event.type) { case SDL_KEYUP: if (event.key.keysym.sym == SDLK_ESCAPE) done = true; break; case SDL_QUIT: done = true; break; } } } printf("FPS: %f\n", frames / accumulatedSeconds); return 0; }