11 /* Render blur in half x half dimenstions. Add one pixel padding in all
12 * directions (2 pixels horizontally, 2 pixels vertically).
14 #define BLUR_BUFFER_WIDTH (320/2 + 2)
15 #define BLUR_BUFFER_HEIGHT (240/2 + 2)
16 #define BLUR_BUFFER_SIZE (BLUR_BUFFER_WIDTH * BLUR_BUFFER_HEIGHT)
17 static unsigned char *blurBuffer, *blurBuffer2;
21 #define THUNDER_RECT_SIZE 2
22 #define THUNDER_RANDOMNESS 16
23 #define THUNDER_SECONDS 0.1f
25 #define VERTEX_COUNT 12
26 #define PERSPECTIVE_NEUTRAL_DEPTH 0.5f
27 #define NEAR_PLANE 0.01f
28 #define ROTATION_SPEED 1.5f
32 /* TODO: Load palette from file */
33 static unsigned short palette[256];
39 MyVertex vertexBuffer[VERTEX_COUNT];
40 MyVertex vertexBufferAnimated[VERTEX_COUNT];
41 MyVertex vertexBufferProjected[VERTEX_COUNT];
43 void clearBlurBuffer();
46 void thunder(int x0, int y0, int x1, int y1, int seed, int randomness, int depth);
51 void renderMesh(int seed);
53 static int init(void);
54 static void destroy(void);
55 static void start(long trans_time);
56 static void stop(long trans_time);
57 static void draw(void);
59 static unsigned int lastFrameTime = 0;
60 static float lastFrameDuration = 0.0f;
61 static struct screen scr = {
70 struct screen *thunder_screen(void)
79 blurBuffer = malloc(BLUR_BUFFER_SIZE);
80 blurBuffer2 = malloc(BLUR_BUFFER_SIZE);
84 /* For now, map to blue */
85 for (i = 0; i < 256; i++) {
86 palette[i] = (i * i) >> 11;
94 static void destroy(void)
103 static void start(long trans_time)
105 lastFrameTime = time_msec;
109 static float remainingThunderDuration = THUNDER_SECONDS;
110 static int thunderPattern = 0;
112 static void draw(void)
114 lastFrameDuration = (time_msec - lastFrameTime) / 1000.0f;
115 lastFrameTime = time_msec;
117 remainingThunderDuration -= lastFrameDuration;
118 if (remainingThunderDuration <= 0) {
120 remainingThunderDuration = THUNDER_SECONDS;
125 renderMesh(thunderPattern);
136 void clearBlurBuffer() {
137 /* Clear the whole buffer (including its padding ) */
138 memset(blurBuffer, 0, BLUR_BUFFER_SIZE);
139 memset(blurBuffer2, 0, BLUR_BUFFER_SIZE);
146 unsigned char *src = blurBuffer + BLUR_BUFFER_WIDTH + 1;
147 unsigned char *dst = blurBuffer2 + BLUR_BUFFER_WIDTH + 1;
149 for (j = 0; j < 120; j++) {
150 for (i = 0; i < 160; i++) {
151 *dst = (*(src - 1) + *(src + 1) + *(src - BLUR_BUFFER_WIDTH) + *(src + BLUR_BUFFER_WIDTH)) >> 2;
153 if (*dst > BLUR_DARKEN) *dst -= BLUR_DARKEN;
159 /* Just skip the padding since we went through the scanline in the inner loop (except from the padding) */
164 /* Swap blur buffers */
166 blurBuffer = blurBuffer2;
171 unsigned int *dst1 = (unsigned int*) vmem_back;
172 unsigned int *dst2 = dst1 + 160; /* We're writing two pixels at once */
173 unsigned char *src1 = blurBuffer + BLUR_BUFFER_WIDTH + 1;
174 unsigned char *src2 = src1 + BLUR_BUFFER_WIDTH;
175 unsigned char tl, tr, bl, br;
178 for (j = 0; j < 120; j++) {
179 for (i = 0; i < 160; i++) {
181 tr = (*src1 + *(src1 + 1)) >> 1;
182 bl = (*src1 + *src2) >> 1;
183 br = tr + ((*src2 + *(src2 + 1)) >> 1) >> 1;
185 /* Pack 2 pixels in each 32 bit word */
186 *dst1 = (palette[tr] << 16) | palette[tl];
187 *dst2 = (palette[br] << 16) | palette[bl];
194 /* Again, skip padding */
198 /* For now, skip a scanline */
205 void thunder(int x0, int y0, int x1, int y1, int seed, int randomness, int depth) {
209 if (randomness <= 0) randomness = 1;
210 mx = ((x0 + x1) >> 1) + rand() % randomness - randomness / 2;
211 my = ((y0 + y1) >> 1) + rand() % randomness - randomness / 2;
212 dst = blurBuffer + BLUR_BUFFER_WIDTH + 1 + mx + my * BLUR_BUFFER_WIDTH;
214 if (depth <= 0) return;
215 if (mx < THUNDER_RECT_SIZE || mx >= 160 - THUNDER_RECT_SIZE || my < THUNDER_RECT_SIZE || my >= 120 - THUNDER_RECT_SIZE) return;
219 for (j = 0; j < THUNDER_RECT_SIZE; j++) {
220 memset(dst, 255, THUNDER_RECT_SIZE);
221 dst += BLUR_BUFFER_WIDTH;
224 thunder(x0, y0, mx, my, rand(), randomness >> 1, depth-1);
225 thunder(mx, my, x1, y1, rand(), randomness >> 1, depth - 1);
228 MyVertex randomVertex() {
232 ret.x = rand() % 200 - 100; if (ret.x == 0) ret.x = 1;
233 ret.y = rand() % 200 - 100; if (ret.y == 0) ret.y = 1;
234 ret.z = rand() % 200 - 100; if (ret.z == 0) ret.z = 1;
237 l = sqrt(ret.x * ret.x + ret.y * ret.y + ret.z * ret.z);
248 for (i = 0; i < VERTEX_COUNT; i++) {
249 vertexBuffer[i] = randomVertex();
258 yRot = ROTATION_SPEED * time_msec / 1000.0f;
260 /* Create rotated basis */
269 bz.x = cos(yRot + PI/2.0f);
271 bz.z = sin(yRot + PI/2.0f);
273 for (i = 0; i < VERTEX_COUNT; i++) {
275 v1 = vertexBuffer[i];
277 /* O re panaia mou */
278 v2.x = v1.x * bx.x + v1.y * by.x + v1.z * bz.x;
279 v2.y = v1.x * bx.y + v1.y * by.y + v1.z * bz.y;
280 v2.z = v1.x * bx.z + v1.y * by.z + v1.z * bz.z;
285 vertexBufferAnimated[i] = v2;
292 for (i = 0; i < VERTEX_COUNT; i++) {
294 if (vertexBufferAnimated[i].z <= NEAR_PLANE) {
295 vertexBufferProjected[i].x = vertexBufferProjected[i].y = 1000.0f;
296 vertexBufferProjected[i].z = -1.0f;
300 vertexBufferProjected[i].x = vertexBufferAnimated[i].x * PERSPECTIVE_NEUTRAL_DEPTH / vertexBufferAnimated[i].z;
301 vertexBufferProjected[i].y = vertexBufferAnimated[i].y * PERSPECTIVE_NEUTRAL_DEPTH / vertexBufferAnimated[i].z;
305 void renderMesh(int seed) {
312 for (vertex = 0; vertex < VERTEX_COUNT; vertex++) {
313 sx = (int)(vertexBufferProjected[vertex].x * 80) + 80;
314 sy = (int)(vertexBufferProjected[vertex].y * 60) + 60;
316 /*if (sx < THUNDER_RECT_SIZE || sx >= 160 - THUNDER_RECT_SIZE || sy < THUNDER_RECT_SIZE || sy >= 120 - THUNDER_RECT_SIZE) return;*/
318 thunder(80, 60, sx, sy, rand(), THUNDER_RANDOMNESS, 5);