po0o+@andrew.cmu.edu (Paul Andrew Olbrich) (04/03/91)
Try this! ------- /* glsperm.c Drew Olbrich, February 1991 Compile with: cc -O sperm.c -o sperm -lgl_s -lm */ #include <stdio.h> #include <math.h> #include "gl.h" #include "device.h" typedef double POINT[2]; typedef double VECTOR[2]; #define VEC_DOT(x, y) (x[0]*y[0] + x[1]*y[1]) #define VEC_LEN(x) (sqrt(x[0]*x[0] + x[1]*x[1])) #define VEC_SET(x, a, b) x[0] = a, x[1] = b #define VEC_COPY(y, x) y[0] = x[0], y[1] = x[1] #define VEC_NEG(x) x[0] = -x[0], x[1] = -x[1] #define VEC_ADD(z, x, y) z[0] = x[0] + y[0], z[1] = x[1] + y[1] #define VEC_SUB(z, x, y) z[0] = x[0] - y[0], z[1] = x[1] - y[1] #define VEC_MULT(x, a) x[0] *= a, x[1] *= a #define VEC_DIV(x, a) x[0] /= a, x[1] /= a #define VEC_ADDS(z, x, a, y) z[0] = x[0] + (a)*y[0], z[1] = x[1] + (a)*y[1] #define VEC_NORM(x) { double l = VEC_LEN(x); VEC_DIV(x, l); } #define COUNT 200 #define WIN_X 1280 #define WIN_Y 1024 typedef struct { POINT x; VECTOR v; double sine, cosine; double vel; } SPERM; SPERM sperm[COUNT]; double rad_scale = 3.5; int index = 0; double frand() { return (rand() % 16384)/16384.0; } init_display() { ginit(); prefsize(WIN_X, WIN_Y); prefposition(0, WIN_X - 1, 0, WIN_Y - 1); foreground(); winopen("sperm"); doublebuffer(); linewidth(3); gconfig(); } init_sperm() { int i; double angle; for (i = 0; i < COUNT; i++) { sperm[i].x[0] = frand()*WIN_X; sperm[i].x[1] = frand()*WIN_Y; VEC_SET(sperm[i].v, 0.0, 0.0); angle = frand()*10.0 + 5.0; sperm[i].sine = sin(angle*M_PI/180.0); sperm[i].cosine = cos(angle*M_PI/180.0); sperm[i].vel = frand()*4.0 + 4.0; } } dynamics() { int i; VECTOR w, old_w; POINT p; double r, dot, temp; int org_x, org_y; VECTOR origin, mouse; int x1, y1, x2, y2; VECTOR target; getorigin(&org_x, &org_y); VEC_SET(origin, (double) org_x, (double) org_y); mouse[0] = getvaluator(MOUSEX); mouse[1] = getvaluator(MOUSEY); VEC_SUB(mouse, mouse, origin); for (i = 0; i < COUNT; i++) { x1 = (int) sperm[i].x[0]; y1 = (int) sperm[i].x[1]; VEC_COPY(target, mouse); VEC_SUB(w, sperm[i].x, target); VEC_NORM(w); VEC_COPY(old_w, w); w[0] = old_w[0]*sperm[i].cosine - old_w[1]*sperm[i].sine; w[1] = old_w[1]*sperm[i].cosine + old_w[0]*sperm[i].sine; VEC_ADDS(p, target, rad_scale*(160.0 - sperm[i].vel*20.0), w); VEC_SUB(w, p, sperm[i].x); VEC_NORM(w); VEC_ADDS(sperm[i].v, sperm[i].v, 1.0, w); VEC_NORM(sperm[i].v); VEC_MULT(sperm[i].v, sperm[i].vel); VEC_ADD(sperm[i].x, sperm[i].x, sperm[i].v); x2 = (int) sperm[i].x[0]; y2 = (int) sperm[i].x[1]; color(BLACK); move2i(x1, y1); draw2i(x2, y2); } } main_loop() { while (!getbutton(RIGHTMOUSE)) { color(WHITE); clear(); dynamics(); swapbuffers(); } } main() { init_display(); init_sperm(); main_loop(); gexit(); }