├── readme.md ├── .gitattributes ├── .gitignore └── main.cpp /readme.md: -------------------------------------------------------------------------------- 1 | This is a visualization of quicksort, with sound. 2 | The pitch of the audio is changed according to which elements are shifting places. 3 | 4 | Programmed in C++ with OpenGL, SDL and Audiere. 5 | 6 | Link to visualization: http://www.youtube.com/watch?v=m1PS8IR6Td0 -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Eclipse 3 | ################# 4 | 5 | *.pydevproject 6 | .project 7 | .metadata 8 | bin/ 9 | tmp/ 10 | *.tmp 11 | *.bak 12 | *.swp 13 | *~.nib 14 | local.properties 15 | .classpath 16 | .settings/ 17 | .loadpath 18 | 19 | # External tool builders 20 | .externalToolBuilders/ 21 | 22 | # Locally stored "Eclipse launch configurations" 23 | *.launch 24 | 25 | # CDT-specific 26 | .cproject 27 | 28 | # PDT-specific 29 | .buildpath 30 | 31 | 32 | ################# 33 | ## Visual Studio 34 | ################# 35 | 36 | ## Ignore Visual Studio temporary files, build results, and 37 | ## files generated by popular Visual Studio add-ons. 38 | 39 | # User-specific files 40 | *.suo 41 | *.user 42 | *.sln.docstates 43 | 44 | # Build results 45 | [Dd]ebug/ 46 | [Rr]elease/ 47 | *_i.c 48 | *_p.c 49 | *.ilk 50 | *.meta 51 | *.obj 52 | *.pch 53 | *.pdb 54 | *.pgc 55 | *.pgd 56 | *.rsp 57 | *.sbr 58 | *.tlb 59 | *.tli 60 | *.tlh 61 | *.tmp 62 | *.vspscc 63 | .builds 64 | *.dotCover 65 | 66 | ## TODO: If you have NuGet Package Restore enabled, uncomment this 67 | #packages/ 68 | 69 | # Visual C++ cache files 70 | ipch/ 71 | *.aps 72 | *.ncb 73 | *.opensdf 74 | *.sdf 75 | 76 | # Visual Studio profiler 77 | *.psess 78 | *.vsp 79 | 80 | # ReSharper is a .NET coding add-in 81 | _ReSharper* 82 | 83 | # Installshield output folder 84 | [Ee]xpress 85 | 86 | # DocProject is a documentation generator add-in 87 | DocProject/buildhelp/ 88 | DocProject/Help/*.HxT 89 | DocProject/Help/*.HxC 90 | DocProject/Help/*.hhc 91 | DocProject/Help/*.hhk 92 | DocProject/Help/*.hhp 93 | DocProject/Help/Html2 94 | DocProject/Help/html 95 | 96 | # Click-Once directory 97 | publish 98 | 99 | # Others 100 | [Bb]in 101 | [Oo]bj 102 | sql 103 | TestResults 104 | *.Cache 105 | ClientBin 106 | stylecop.* 107 | ~$* 108 | *.dbmdl 109 | Generated_Code #added for RIA/Silverlight projects 110 | 111 | # Backup & report files from converting an old project file to a newer 112 | # Visual Studio version. Backup files are not needed, because we have git ;-) 113 | _UpgradeReport_Files/ 114 | Backup*/ 115 | UpgradeLog*.XML 116 | 117 | 118 | 119 | ############ 120 | ## Windows 121 | ############ 122 | 123 | # Windows image file caches 124 | Thumbs.db 125 | 126 | # Folder config file 127 | Desktop.ini 128 | 129 | 130 | ############# 131 | ## Python 132 | ############# 133 | 134 | *.py[co] 135 | 136 | # Packages 137 | *.egg 138 | *.egg-info 139 | dist 140 | build 141 | eggs 142 | parts 143 | bin 144 | var 145 | sdist 146 | develop-eggs 147 | .installed.cfg 148 | 149 | # Installer logs 150 | pip-log.txt 151 | 152 | # Unit test / coverage reports 153 | .coverage 154 | .tox 155 | 156 | #Translations 157 | *.mo 158 | 159 | #Mr Developer 160 | .mr.developer.cfg 161 | 162 | # Mac crap 163 | .DS_Store 164 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * 20.01.12 Quicksort 3 | * Author: teaprog 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | using namespace audiere; 10 | 11 | #include 12 | using std::vector; 13 | 14 | int screen_w = 1800; 15 | int screen_h = 950; 16 | 17 | bool quit = false; 18 | 19 | SDL_Event event; 20 | 21 | const int POLE_NUMBER = 500; 22 | 23 | class Pole; 24 | 25 | void init(); 26 | void reshape(int, int); 27 | void display(); 28 | void drawAndInputHandle(); 29 | void shuffle(); 30 | 31 | void quickSort(Pole [], int); 32 | void quickSort(Pole [], int, int, int); 33 | int partition(Pole [], int, int, int); 34 | 35 | AudioDevicePtr device(OpenDevice()); 36 | OutputStreamPtr stream(OpenSound(device, "sound.wav", false)); 37 | void playSound(int); 38 | 39 | int maxHeight = 0; 40 | int minHeight = 9999999; 41 | 42 | class Pole { 43 | private: 44 | GLfloat xPos; 45 | GLfloat yPos; 46 | int height; 47 | GLfloat width; 48 | 49 | GLfloat colorR1, colorG1, colorB1; 50 | GLfloat colorR2, colorG2, colorB2; 51 | 52 | static int poleCounter; 53 | public: 54 | Pole() { 55 | GLfloat spaceBetween = 0.0f; 56 | width = (screen_w - 20.0f - POLE_NUMBER * spaceBetween) / (POLE_NUMBER); 57 | changeHeight(); 58 | 59 | xPos = 10.0f + poleCounter * (width + spaceBetween); 60 | yPos = screen_h - 100.0f; 61 | 62 | poleCounter++; 63 | 64 | setStandardColor(); 65 | } 66 | 67 | void setStandardColor() { 68 | colorR1 = 0.0f; 69 | colorG1 = 0.3f; 70 | colorB1 = 0.0f; 71 | 72 | colorR2 = 0.0f; 73 | colorG2 = 0.0f; 74 | colorB2 = 1.0f; 75 | } 76 | 77 | void setActionColor() { 78 | colorR1 = 1.0f; 79 | colorG1 = 0.0f; 80 | colorB1 = 0.0f; 81 | 82 | colorR2 = 1.0f; 83 | colorG2 = 0.0f; 84 | colorB2 = 0.0f; 85 | } 86 | 87 | void setFinishedColor() { 88 | colorR1 = 0.0f; 89 | colorG1 = 0.5f; 90 | colorB1 = 0.0f; 91 | 92 | colorR2 = 0.0f; 93 | colorG2 = 1.0f; 94 | colorB2 = 0.0f; 95 | } 96 | 97 | void changeHeight() { 98 | height = rand() % (screen_h - 200); 99 | 100 | if (height > maxHeight) 101 | maxHeight = height; 102 | if (height < minHeight) 103 | minHeight = height; 104 | } 105 | 106 | void setHeight(int height) { 107 | this->height = height; 108 | } 109 | 110 | int getHeight() { 111 | return height; 112 | } 113 | 114 | void drawPole() { 115 | glColor3f(colorR1, colorG1, colorB1); 116 | glBegin(GL_TRIANGLE_FAN); 117 | glVertex2f(xPos, yPos); 118 | glVertex2f(xPos + width, yPos); 119 | glColor3f(colorR2, colorG2, colorB2); 120 | glVertex2f(xPos + width, yPos - height); 121 | glVertex2f(xPos, yPos - height); 122 | glEnd(); 123 | } 124 | } pole[POLE_NUMBER]; 125 | 126 | int Pole::poleCounter = 0; 127 | 128 | void drawAndInputHandle() { 129 | while (SDL_PollEvent(&event)) { 130 | switch (event.type) { 131 | case SDL_QUIT: 132 | quit = true; 133 | return; 134 | break; 135 | case SDL_KEYDOWN: 136 | if (event.key.keysym.sym == SDLK_ESCAPE) { 137 | quit = true; 138 | return; 139 | } 140 | else if (event.key.keysym.sym == SDLK_SPACE) 141 | shuffle(); 142 | break; 143 | case SDL_VIDEORESIZE: 144 | reshape(event.resize.w, event.resize.h); 145 | break; 146 | default: 147 | break; 148 | } 149 | } 150 | 151 | glClear(GL_COLOR_BUFFER_BIT); 152 | glLoadIdentity(); 153 | 154 | for (int i = 0; i < POLE_NUMBER; i++) 155 | pole[i].drawPole(); 156 | 157 | SDL_GL_SwapBuffers(); 158 | } 159 | 160 | void shuffle() { 161 | for (int i = 0; i < POLE_NUMBER; i++) { 162 | pole[i].changeHeight(); 163 | pole[i].setStandardColor(); 164 | } 165 | 166 | stream->reset(); 167 | stream->play(); 168 | quickSort(pole, POLE_NUMBER); 169 | } 170 | 171 | void quickSort(Pole pole[], int arrayLength) { 172 | quickSort(pole, arrayLength, 0, arrayLength-1); 173 | } 174 | 175 | void quickSort(Pole pole[], int arrayLength, int first, int last) { 176 | if (quit) 177 | return; 178 | 179 | if (last > first) { 180 | int pivot = partition(pole, arrayLength, first, last); 181 | pole[pivot].setFinishedColor(); 182 | quickSort(pole, arrayLength, first, pivot-1); 183 | quickSort(pole, arrayLength, pivot+1, last); 184 | } 185 | else { 186 | pole[first].setFinishedColor(); 187 | } 188 | } 189 | 190 | int partition(Pole pole[], int arrayLength, int first, int last) { 191 | int pivot = pole[first].getHeight(); 192 | int low = first+1; 193 | int high = last; 194 | 195 | while (high > low) { 196 | if (quit) 197 | return 0; 198 | 199 | while (low <= high && pole[low].getHeight() <= pivot) 200 | low++; 201 | while (low <= high && pole[high].getHeight() > pivot) 202 | high--; 203 | 204 | if (high > low) { 205 | int temp = pole[high].getHeight(); 206 | pole[high].setHeight(pole[low].getHeight()); 207 | pole[high].setActionColor(); 208 | playSound(pole[high].getHeight()); 209 | pole[low].setHeight(temp); 210 | pole[low].setActionColor(); 211 | playSound(pole[low].getHeight()); 212 | drawAndInputHandle(); 213 | pole[high].setStandardColor(); 214 | pole[low].setStandardColor(); 215 | } 216 | } 217 | 218 | while (high > first && pole[high].getHeight() >= pivot) 219 | high--; 220 | 221 | if (pivot > pole[high].getHeight()) { 222 | pole[first].setHeight(pole[high].getHeight()); 223 | pole[first].setActionColor(); 224 | playSound(pole[first].getHeight()); 225 | pole[high].setHeight(pivot); 226 | pole[high].setActionColor(); 227 | playSound(pole[high].getHeight()); 228 | drawAndInputHandle(); 229 | pole[first].setStandardColor(); 230 | pole[high].setStandardColor(); 231 | return high; 232 | } 233 | else { 234 | return first; 235 | } 236 | } 237 | 238 | void playSound(int poleHeight) { 239 | stream->reset(); 240 | stream->setPitchShift((static_cast(poleHeight)/(maxHeight-minHeight)*1.7f)+0.2f); 241 | stream->play(); 242 | } 243 | 244 | void init() { 245 | SDL_Init(SDL_INIT_EVERYTHING); 246 | SDL_WM_SetCaption("20.01.12 Quicksort", 0); 247 | SDL_putenv("SDL_VIDEO_CENTERED=center"); 248 | SDL_ShowCursor(0); 249 | 250 | reshape(screen_w, screen_h); 251 | 252 | stream->setVolume(0.3f); 253 | 254 | stream->play(); 255 | 256 | glClearColor(0.5f, 0.5f, 0.5f, 0.0f); 257 | } 258 | 259 | void reshape(int screenW, int screenH) { 260 | screen_w = screenW; 261 | screen_h = screenH; 262 | 263 | SDL_SetVideoMode(screenW, screenH, 32, SDL_OPENGL | SDL_RESIZABLE); 264 | glViewport(0, 0, screenW, screenH); 265 | glMatrixMode(GL_PROJECTION); 266 | glLoadIdentity(); 267 | glOrtho(0.0, screen_w, screen_h, 0.0, -1.0, 1.0); 268 | glMatrixMode(GL_MODELVIEW); 269 | } 270 | 271 | void display() { 272 | glClear(GL_COLOR_BUFFER_BIT); 273 | glLoadIdentity(); 274 | 275 | for (int i = 0; i < POLE_NUMBER; i++) 276 | pole[i].drawPole(); 277 | 278 | SDL_GL_SwapBuffers(); 279 | } 280 | 281 | int main(int argc, char** argv) { 282 | init(); 283 | 284 | quickSort(pole, POLE_NUMBER); 285 | 286 | while (!quit) { 287 | while (SDL_PollEvent(&event)) { 288 | switch (event.type) { 289 | case SDL_QUIT: 290 | quit = true; 291 | break; 292 | case SDL_KEYDOWN: 293 | if (event.key.keysym.sym == SDLK_ESCAPE) 294 | quit = true; 295 | else if (event.key.keysym.sym == SDLK_SPACE) 296 | shuffle(); 297 | break; 298 | case SDL_VIDEORESIZE: 299 | reshape(event.resize.w, event.resize.h); 300 | break; 301 | default: 302 | break; 303 | } 304 | } 305 | 306 | display(); 307 | } 308 | 309 | SDL_Quit(); 310 | return 0; 311 | } --------------------------------------------------------------------------------