/* lineblob.c - Something Author Jani Kniivilä compile with: gcc -o lineblob lineblob.c -lSDL -lpthread -ltSGGL */ #include #include #include #include #define WIDTH 640 /* width */ #define HEIGHT 480 /* and height of the screen */ #define BLOB_X 200 #define BLOB_Y 240 #define PRECISION 64 SDL_Surface *surface; gfx_image_t *output; typedef struct { float x, y, z, rx, ry, rz; int sx, sy; } vertex_t; vertex_t *vertices, *original; gfx_color_t *background_color; gfx_color_t *bg_line_color; gfx_color_t *blob_color; gfx_hline_t *hlines; const float my_pi = 3.141593; void rotate_vertex(vertex_t *v, float xa, float ya, float za) { vertex_t t; v->rx = v->x; v->ry = v->y; v->rz = v->z; t.ry = v->ry * cos(xa) - v->rz * sin(xa); t.rz = v->rz * cos(xa) + v->ry * sin(xa); v->ry = t.ry; v->rz = t.rz; t.rz = v->rz * cos(ya) - v->rx * sin(ya); t.rx = v->rx * cos(ya) + v->rz * sin(ya); v->rz = t.rz; v->rx = t.rx; t.rx = v->rx * cos(za) - v->ry * sin(za); t.ry = v->ry * cos(za) + v->rx * sin(za); v->rx = t.rx; v->ry = t.ry; } void project_vertex_d(vertex_t *v, int distance) { v->sx = (int)(256 * v->rx / (distance - v->rz)); v->sy = (int)(256 * v->ry / (distance - v->rz)); } void draw_background() { int i; static float theta = 0.0; for (i = 0; i < output->height; i++) { hlines[i].x1 = output->max_x - (output->mid_x>>2) + 50 * sin(theta+i*my_pi/output->mid_y) * cos(1.123*theta+i*my_pi/(output->mid_y>>1)) + 10 * sin(1.56 * theta); } gfx_hlines(hlines, output->height, output); theta += my_pi/26.0; } void calc_blob(float angle) { int i, c, p; float k; for (c = 0; c < PRECISION; c++) { k = 2 + cos(angle + c*4 * my_pi/PRECISION); for (i = 0; i < PRECISION; i++) { p = i + c * PRECISION; vertices[p].x = original[p].x * k; vertices[p].y = original[p].y; vertices[p].z = original[p].z * k; rotate_vertex(&vertices[p], -0.1, 0, 0); project_vertex_d(&vertices[p], 256); } } } void draw_blob() { int i, c, p; for (c = 0; c < PRECISION; c++) { p = c * PRECISION; for (i = 0; i < PRECISION-1; i++) { gfx_slow_addline( BLOB_X + vertices[p].sx, BLOB_Y + vertices[p].sy, BLOB_X + vertices[p+1].sx, BLOB_Y + vertices[p+1].sy, blob_color, output); p++; } gfx_slow_addline( BLOB_X + vertices[p].sx, BLOB_Y + vertices[p].sy, BLOB_X + vertices[p-PRECISION+1].sx, BLOB_Y + vertices[p-PRECISION+1].sy, blob_color, output); } for (c = 0; c < PRECISION-1; c++) { p = c * PRECISION; for (i = 0; i < PRECISION; i++) { gfx_slow_addline( BLOB_X + vertices[p].sx, BLOB_Y + vertices[p].sy, BLOB_X + vertices[p+PRECISION].sx, BLOB_Y + vertices[p+PRECISION].sy, blob_color, output); p++; } } } int fx_init() { int i, j, k; /* * Initialize SDL and open proper graphics mode/window */ if (SDL_Init(SDL_INIT_VIDEO) < 0) return -1; atexit(SDL_Quit); surface = SDL_SetVideoMode(WIDTH, HEIGHT, 16, SDL_SWSURFACE); if (!surface) return -2; /* * Create a "link" to SDL */ output = gfx_create_null_image(WIDTH, HEIGHT); /* create an image without pixel-data */ if (!output) return -3; output->data = (Uint16 *) surface->pixels; /* redirect the pixels to "screen" */ /* * Allocate and Initialize blob co-ordinates */ vertices = (vertex_t *) calloc(PRECISION*PRECISION, sizeof(vertex_t)); if (!vertices) return -4; original = (vertex_t *) calloc(PRECISION*PRECISION, sizeof(vertex_t)); if (!original) return -5; k = 0; for (j = 0; j < PRECISION; j++) { for (i = 0; i < PRECISION; i++) { original[k].x = cos(i * 2*my_pi/PRECISION) * 50; original[k].y = (j - (PRECISION/2)) * 10; original[k].z = sin(i * 2*my_pi/PRECISION) * 50; k++; } } /* * Specify colors */ blob_color = gfx_alloc_color(64, 64, 64); background_color = gfx_alloc_color(128, 92, 0); bg_line_color = gfx_alloc_color(92, 64, 0); /* * Initialize the sine-wave in background */ hlines = (gfx_hline_t *) calloc(output->height, sizeof(gfx_hline_t)); if (!hlines) return -6; for (i = 0; i < output->height; i++) { hlines[i].x2 = output->max_x; hlines[i].y = i; hlines[i].color = bg_line_color; } return 0; } void fx_shutdown() { gfx_dispose_color(background_color); gfx_dispose_color(bg_line_color); gfx_dispose_color(blob_color); free(hlines); free(vertices); free(original); free(output); } int fx_draw_frame() { static float angle = 0; if (SDL_MUSTLOCK(surface)) SDL_LockSurface(surface); gfx_fill(background_color, output); draw_background(); calc_blob(angle); draw_blob(); if (SDL_MUSTLOCK(surface)) SDL_UnlockSurface(surface); SDL_Flip(surface); angle += my_pi/75.0; return 0; } int main() { SDL_Event event; int done = 0; if (fx_init()) return -1; while (!done) { fx_draw_frame(); while (SDL_PollEvent(&event)) { switch (event.type) { case SDL_QUIT: case SDL_KEYDOWN: case SDL_MOUSEBUTTONDOWN: done = 1; } } } fx_shutdown(); return 0; }