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
21 double spin_x_speed, spin_y_speed, spin_z_speed;
24 double rotx, roty, rotz; /* current object rotation */
25 double dx, dy, dz; /* current rotational velocity */
26 double ddx, ddy, ddz; /* current rotational acceleration */
27 double d_max; /* max rotational velocity */
29 int wander_frame; /* position in the wander cycle */
35 #define ABS(x) ((x)<0?-(x):(x))
37 #define BELLRAND(n) ((frand((n)) + frand((n)) + frand((n))) / 3)
38 #define RANDSIGN() ((random() & 1) ? 1 : -1)
41 rotate_1 (double *pos, double *v, double *dv, double speed, double max_v)
45 if (speed == 0) return;
58 if (ppos < 0) abort();
59 if (ppos > 1.0) abort();
60 *pos = (*pos > 0 ? ppos : -ppos);
66 if (*v > max_v || *v < -max_v)
70 /* If it stops, start it going in the other direction. */
77 /* keep going in the same direction */
92 /* Alter direction of rotational acceleration randomly. */
93 if (! (random() % 120))
96 /* Change acceleration very occasionally. */
97 if (! (random() % 200))
101 else if (random() & 1)
109 /* Returns a rotator object, which encapsulates rotation and motion state.
111 spin_[xyz]_speed indicates the relative speed of rotation.
112 Specify 0 if you don't want any rotation around that axis.
114 spin_accel specifies a scaling factor for the acceleration that is
115 randomly applied to spin: if you want the speed to change faster,
118 wander_speed indicates the relative speed through space.
120 If randomize_initial_state_p is true, then the initial position and
121 rotation will be randomized (even if the spin speeds are 0.) If it
122 is false, then all values will be initially zeroed.
125 make_rotator (double spin_x_speed,
130 int randomize_initial_state_p)
132 rotator *r = (rotator *) calloc (1, sizeof(*r));
137 if (spin_x_speed < 0 || spin_y_speed < 0 || spin_z_speed < 0 ||
141 r->spin_x_speed = spin_x_speed;
142 r->spin_y_speed = spin_y_speed;
143 r->spin_z_speed = spin_z_speed;
144 r->wander_speed = wander_speed;
146 if (randomize_initial_state_p)
148 r->rotx = frand(1.0) * RANDSIGN();
149 r->roty = frand(1.0) * RANDSIGN();
150 r->rotz = frand(1.0) * RANDSIGN();
152 r->wander_frame = random() % 0xFFFF;
156 r->rotx = r->roty = r->rotz = 0;
163 r->dx = BELLRAND(d * r->spin_x_speed);
164 r->dy = BELLRAND(d * r->spin_y_speed);
165 r->dz = BELLRAND(d * r->spin_z_speed);
167 r->d_max = r->dx * 2;
169 r->ddx = (dd + frand(dd+dd)) * r->spin_x_speed * spin_accel;
170 r->ddy = (dd + frand(dd+dd)) * r->spin_y_speed * spin_accel;
171 r->ddz = (dd + frand(dd+dd)) * r->spin_z_speed * spin_accel;
174 fprintf (stderr, "rotator:\n");
175 fprintf (stderr, " wander: %3d %6.2f\n", r->wander_frame, r->wander_speed);
176 fprintf (stderr, " speed: %6.2f %6.2f %6.2f\n",
177 r->spin_x_speed, r->spin_y_speed, r->spin_z_speed);
178 fprintf (stderr, " rot: %6.2f %6.2f %6.2f\n",
179 r->rotx, r->roty, r->rotz);
180 fprintf (stderr, " d: %6.2f %6.2f %6.2f, %6.2f\n",
183 fprintf (stderr, " dd: %6.2f %6.2f %6.2f\n",
184 r->ddx, r->ddy, r->ddz);
192 free_rotator (rotator *r)
198 get_rotation (rotator *rot, double *x_ret, double *y_ret, double *z_ret,
204 rotate_1 (&rot->rotx, &rot->dx, &rot->ddx, rot->spin_x_speed, rot->d_max);
205 rotate_1 (&rot->roty, &rot->dy, &rot->ddy, rot->spin_y_speed, rot->d_max);
206 rotate_1 (&rot->rotz, &rot->dz, &rot->ddz, rot->spin_z_speed, rot->d_max);
212 if (x < 0) x = 1 - (x + 1);
213 if (y < 0) y = 1 - (y + 1);
214 if (z < 0) z = 1 - (z + 1);
216 if (x_ret) *x_ret = x;
217 if (y_ret) *y_ret = y;
218 if (z_ret) *z_ret = z;
223 get_position (rotator *rot, double *x_ret, double *y_ret, double *z_ret,
226 double x = 0.5, y = 0.5, z = 0.5;
228 if (rot->wander_speed != 0)
233 # define SINOID(F) ((1 + sin((rot->wander_frame * (F)) / 2 * M_PI)) / 2.0)
234 x = SINOID (0.71 * rot->wander_speed);
235 y = SINOID (0.53 * rot->wander_speed);
236 z = SINOID (0.37 * rot->wander_speed);
240 if (x_ret) *x_ret = x;
241 if (y_ret) *y_ret = y;
242 if (z_ret) *z_ret = z;