1 /* xscreensaver, Copyright (c) 1998-2002 Jamie Zawinski <jwz@jwz.org>
3 * Permission to use, copy, modify, distribute, and sell this software and its
4 * documentation for any purpose is hereby granted without fee, provided that
5 * the above copyright notice appear in all copies and that both that
6 * copyright notice and this permission notice appear in supporting
7 * documentation. No representations are made about the suitability of this
8 * software for any purpose. It is provided "as is" without express or
25 double spin_x_speed, spin_y_speed, spin_z_speed;
28 double rotx, roty, rotz; /* current object rotation */
29 double dx, dy, dz; /* current rotational velocity */
30 double ddx, ddy, ddz; /* current rotational acceleration */
31 double d_max; /* max rotational velocity */
33 int wander_frame; /* position in the wander cycle */
39 #define ABS(x) ((x)<0?-(x):(x))
41 #define BELLRAND(n) ((frand((n)) + frand((n)) + frand((n))) / 3)
42 #define RANDSIGN() ((random() & 1) ? 1 : -1)
45 rotate_1 (double *pos, double *v, double *dv, double speed, double max_v)
49 if (speed == 0) return;
62 if (ppos < 0) abort();
63 if (ppos > 1.0) abort();
64 *pos = (*pos > 0 ? ppos : -ppos);
70 if (*v > max_v || *v < -max_v)
74 /* If it stops, start it going in the other direction. */
81 /* keep going in the same direction */
96 /* Alter direction of rotational acceleration randomly. */
97 if (! (random() % 120))
100 /* Change acceleration very occasionally. */
101 if (! (random() % 200))
105 else if (random() & 1)
113 /* Returns a rotator object, which encapsulates rotation and motion state.
115 spin_[xyz]_speed indicates the relative speed of rotation.
116 Specify 0 if you don't want any rotation around that axis.
118 spin_accel specifies a scaling factor for the acceleration that is
119 randomly applied to spin: if you want the speed to change faster,
122 wander_speed indicates the relative speed through space.
124 If randomize_initial_state_p is true, then the initial position and
125 rotation will be randomized (even if the spin speeds are 0.) If it
126 is false, then all values will be initially zeroed.
129 make_rotator (double spin_x_speed,
134 int randomize_initial_state_p)
136 rotator *r = (rotator *) calloc (1, sizeof(*r));
141 if (spin_x_speed < 0 || spin_y_speed < 0 || spin_z_speed < 0 ||
145 r->spin_x_speed = spin_x_speed;
146 r->spin_y_speed = spin_y_speed;
147 r->spin_z_speed = spin_z_speed;
148 r->wander_speed = wander_speed;
150 if (randomize_initial_state_p)
152 r->rotx = frand(1.0) * RANDSIGN();
153 r->roty = frand(1.0) * RANDSIGN();
154 r->rotz = frand(1.0) * RANDSIGN();
156 r->wander_frame = random() % 0xFFFF;
160 r->rotx = r->roty = r->rotz = 0;
167 r->dx = BELLRAND(d * r->spin_x_speed);
168 r->dy = BELLRAND(d * r->spin_y_speed);
169 r->dz = BELLRAND(d * r->spin_z_speed);
171 r->d_max = r->dx * 2;
173 r->ddx = (dd + frand(dd+dd)) * r->spin_x_speed * spin_accel;
174 r->ddy = (dd + frand(dd+dd)) * r->spin_y_speed * spin_accel;
175 r->ddz = (dd + frand(dd+dd)) * r->spin_z_speed * spin_accel;
178 fprintf (stderr, "rotator:\n");
179 fprintf (stderr, " wander: %3d %6.2f\n", r->wander_frame, r->wander_speed);
180 fprintf (stderr, " speed: %6.2f %6.2f %6.2f\n",
181 r->spin_x_speed, r->spin_y_speed, r->spin_z_speed);
182 fprintf (stderr, " rot: %6.2f %6.2f %6.2f\n",
183 r->rotx, r->roty, r->rotz);
184 fprintf (stderr, " d: %6.2f %6.2f %6.2f, %6.2f\n",
187 fprintf (stderr, " dd: %6.2f %6.2f %6.2f\n",
188 r->ddx, r->ddy, r->ddz);
196 free_rotator (rotator *r)
202 get_rotation (rotator *rot, double *x_ret, double *y_ret, double *z_ret,
208 rotate_1 (&rot->rotx, &rot->dx, &rot->ddx, rot->spin_x_speed, rot->d_max);
209 rotate_1 (&rot->roty, &rot->dy, &rot->ddy, rot->spin_y_speed, rot->d_max);
210 rotate_1 (&rot->rotz, &rot->dz, &rot->ddz, rot->spin_z_speed, rot->d_max);
216 if (x < 0) x = 1 - (x + 1);
217 if (y < 0) y = 1 - (y + 1);
218 if (z < 0) z = 1 - (z + 1);
220 if (x_ret) *x_ret = x;
221 if (y_ret) *y_ret = y;
222 if (z_ret) *z_ret = z;
227 get_position (rotator *rot, double *x_ret, double *y_ret, double *z_ret,
230 double x = 0.5, y = 0.5, z = 0.5;
232 if (rot->wander_speed != 0)
237 # define SINOID(F) ((1 + sin((rot->wander_frame * (F)) / 2 * M_PI)) / 2.0)
238 x = SINOID (0.71 * rot->wander_speed);
239 y = SINOID (0.53 * rot->wander_speed);
240 z = SINOID (0.37 * rot->wander_speed);
244 if (x_ret) *x_ret = x;
245 if (y_ret) *y_ret = y;
246 if (z_ret) *z_ret = z;