cfa45f3be2599866683c407ce2a5e6ed525a68b6
[swarmPDK.git] / src / swarm.cpp
1 #include <stdio.h>
2 #include <math.h>
3
4 #include <GLES/gl.h>
5 #include "SDL.h"
6 #include "PDL.h"
7 #include "Pixel.h"
8
9 #define NPIXELS 2500
10 #define SCREENW 320
11 #define SCREENH 480
12
13 SDL_Surface* screen;               // Screen surface
14 Uint16 mx, my;
15 Pixel** pixels;
16 GLfloat* vertices;
17
18 #ifdef WIN32
19 extern "C" 
20 #endif
21 GL_API int GL_APIENTRY _dgles_load_library(void *, void *(*)(void *, const char *));
22
23 static void *proc_loader(void *h, const char *name)
24 {
25     (void) h;
26     return SDL_GL_GetProcAddress(name);
27 }
28
29 void init() {
30         // Set up OpenGL
31         glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
32         glMatrixMode(GL_PROJECTION);
33         glLoadIdentity();
34         glOrthof(0.0f, (float)screen->w, (float)screen->h, 0.0f, -1.0f, 1.0f);
35         glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
36
37         // Initialize vertices
38         vertices = new GLfloat[NPIXELS * 6];
39         memset(vertices, 0, sizeof(GLfloat) * NPIXELS * 6);
40         glEnableClientState(GL_VERTEX_ARRAY);
41         glVertexPointer(3, GL_FLOAT, 0, vertices);
42
43         // Center cursor
44         mx = screen->w / 2;
45         my = screen->h / 2;
46
47         // Initialize pixel objects
48         pixels = new Pixel*[NPIXELS];
49         for (int x = 0; x < NPIXELS; x++) {
50                 pixels[x] = new Pixel(screen);
51         }
52
53 }
54
55 void pushPixels(int pushX, int pushY) {
56         // Apply force to each pixel outwards from the mouse
57         for (int i = 0; i < NPIXELS; i++) {
58                 // Get the direction
59                 float dx = pixels[i]->x - pushX;
60                 float dy = pixels[i]->y - pushY;
61                 float mag = sqrtf(dx*dx + dy*dy);
62                 dx /= mag;
63                 dy /= mag;
64
65                 // Apply force.
66                 pixels[i]->accel(dx * 10.0, dy * 10.0);
67         }
68 }
69
70 void engine() {
71         // Clear the canvas
72         glClear(GL_COLOR_BUFFER_BIT);
73
74         // Update cursor
75         vertices[0] = mx - 5;
76         vertices[1] = my - 5;
77         vertices[3] = mx + 5;
78         vertices[4] = my - 5;
79         vertices[6] = mx + 5;
80         vertices[7] = my + 5;
81         vertices[9] = mx - 5;
82         vertices[10] = my + 5;
83         glDrawArrays(GL_LINE_LOOP, 0, 4);
84
85         // Update all pixel objects
86         for (int i = 0; i < NPIXELS; i++) {
87                 // Get distance
88                 float dx = mx - pixels[i]->x;
89                 float dy = my - pixels[i]->y;
90                 float d = sqrtf(dx*dx + dy*dy);
91
92                 // Apply acceleration to pixels towards the mouse cursor
93                 float ax = dx / 50.0;
94                 float ay = dy / 50.0;
95
96                 // Apply a drag proportional to the distance from the cursor
97                 if (d > 25.0) {
98                         ax += -pixels[i]->vx * (d - 25.0) / 1000.0;
99                         ay += -pixels[i]->vy * (d - 25.0) / 1000.0;
100                 }
101
102                 // And a "chaotic" acceleration inversely proportional
103                 // to the distance from the cursor
104                 ax += ((rand() / (float)RAND_MAX) * 40.0 - 20.0) / d;
105                 ay += ((rand() / (float)RAND_MAX) * 40.0 - 20.0) / d;
106
107                 pixels[i]->accel(ax,ay);
108                 pixels[i]->update();
109                 pixels[i]->draw(&vertices[i*6]);
110         }
111         glDrawArrays(GL_LINES, 0, NPIXELS * 2);
112 }
113
114 int main(int argc, char** argv)
115 {
116     // Initialize the SDL library with the Video subsystem
117     SDL_Init(SDL_INIT_VIDEO);
118
119     // start the PDL library
120     PDL_Init(0);
121     
122     // Tell it to use OpenGL ES version 1.1
123     SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 1);
124
125     // Set the video mode to full screen with OpenGL-ES support
126     screen = SDL_SetVideoMode(SCREENW, SCREENH, 0, SDL_OPENGL);
127     if (!screen) {
128                 printf("Could not initialize video!\n");
129                 exit(1);
130     }
131     printf("width: %d, height, %d\n", screen->w, screen->h);
132         printf("Starting up with %d pixels\n", NPIXELS);
133
134 #if WIN32
135     // Load the desktop OpenGL-ES emulation library
136     _dgles_load_library(NULL, proc_loader);
137 #endif
138
139         init();
140
141     // Event descriptor
142     SDL_Event Event;
143         int app_is_active = 1;
144         Uint32 last = SDL_GetTicks();
145         int fps_counter = 0;
146
147     do {
148         // Process the events
149                 if (!app_is_active)
150                         SDL_WaitEvent(NULL);
151         while (SDL_PollEvent(&Event)) {
152             switch (Event.type) {
153                                 case SDL_MOUSEMOTION:
154                                         mx = Event.motion.x;
155                                         my = Event.motion.y;
156                                         break;
157                                 case SDL_MOUSEBUTTONDOWN:
158                                         pushPixels(Event.button.x, Event.button.y);
159                                 case SDL_ACTIVEEVENT:
160                                         if (Event.active.state == SDL_APPACTIVE)
161                                                 app_is_active = Event.active.gain;
162                                         break;
163                 default:
164                     break;
165             }
166         }
167
168                 engine();
169                 glFlush();
170                 SDL_GL_SwapBuffers();
171
172                 // Calculate FPS
173                 fps_counter++;
174                 Uint32 now = SDL_GetTicks();
175                 if (now - last > 1000) {
176                         printf("%d FPS\n", fps_counter);
177                         fps_counter = 0;
178                         last = now;
179                 }
180     } while (Event.type != SDL_QUIT);
181     // We exit anytime we get a request to quit the app
182
183     // Cleanup
184     PDL_Quit();
185     SDL_Quit();
186
187     return 0;
188 }