1 /*
2 * drone.cc
3 * DIN Is Noise is copyright (c) 2006-2021 Jagannathan Sampath
4 * DIN Is Noise is released under GNU Public License 2.0
5 * For more information, please visit https://dinisnoise.org/
6 */
7
8 #include "din.h"
9 #include "drone.h"
10 #include "console.h"
11 #include "audio.h"
12 #include "utils.h"
13 #include "vector2d.h"
14 #include <math.h>
15 using namespace std;
16
17 extern multi_curve drone_mod_am_crv, drone_mod_fm_crv;
18 extern solver warp_vol, warp_pitch;
19 extern const char spc;
20
21 extern void get (float& g, float& gx, float& gy, defvelaccel& dva);
22 extern int gethandlesize ();
23 extern int gettrailsize ();
24 extern const float TWO_PI;
25
setis()26 void drone::setis () {
27 if (IS == DRONE_OR_NOISE) is = get_rand_bit (); else is = IS;
28 }
29
drone(float bottom)30 drone::drone (float bottom) : mod (&drone_mod_fm_crv, &drone_mod_am_crv) {
31
32 setis ();
33 step = vol = 0;
34 range = 0;
35 pos = 0.0f;
36 r = g = b = 0.5f;
37 cx = cy = 0;
38 x = y = 0;
39 dy = 0;
40 xv = x; yv = y;
41 xa = x; ya = y;
42 sx = 0;
43 sel = 0;
44 state = DEAD;
45 frozen = 0;
46 froze_at = 0;
47 handle_size = gethandlesize ();
48 trail.set (gettrailsize());
49 id = ++UID;
50 get (V, vx, vy, v0);
51 v_mult = 1.0f;
52 get (A, ax, ay, a0);
53 gravity = 0;
54 attractor = 0;
55 orbiting = 0;
56 launcher = 0;
57 tracking = 0;
58 tracked_drone = 0;
59 dpm = 60;
60 ++ref;
61 launched_by = 0;
62 reincarnate = 0;
63 switch (ARE) {
64 case IMMORTAL:
65 birth = -1;
66 break;
67 case MORTAL:
68 birth = ui_clk ();
69 break;
70 case REINCARNATE:
71 birth = ui_clk ();
72 reincarnate = 1;
73 break;
74 }
75 life = LIFETIME;
76 insert = INSERTTIME;
77 target = 0;
78 cur_target = 0;
79 num_targets = 0;
80 update_pv = UNSET;
81 snap = 0;
82 nconn = 0;
83 type = CHAIN;
84 gab.set (1.0f, 0.0f, 0, 1.0f);
85 tovol = 0.0f;
86 finl = 0;
87 note_num = -1;
88 }
89
~drone()90 drone::~drone () {
91 --ref;
92 }
93
94
move_center()95 void drone::move_center () {
96 cx += (x - xi);
97 cy += (y - yi);
98 }
99
eval_conns()100 drone* drone::eval_conns () {
101 if (nconn) {
102 int n = 0;
103 proc_conn [this] = true;
104 list<double>::iterator mi = mags.begin();
105 drone_iterator p = connections.begin ();
106 drone* c0 = *p;
107 for (drone_iterator q = connections.end (); p != q; ++p, ++mi) {
108 drone* pdc = *p;
109 if (proc_conn[pdc] == false) {
110 proc_conn [pdc] = true;
111 drone& dc = *pdc;
112 double now = magnitude (cx, cy, dc.cx, dc.cy);
113 double org = *mi;
114 if (now > org) {
115 double lead = STIFFNESS * (now - org);
116 float ux, uy; unit_vector<float, int> (ux, uy, dc.cx, dc.cy, cx, cy);
117 dc.set_center (dc.cx + lead * ux, dc.cy + lead * uy);
118 ++n;
119 }
120 }
121 }
122 if (n) return this; else return c0;
123 }
124 return 0;
125 }
126
remagconns()127 void drone::remagconns () {
128 list<double>::iterator mi = mags.begin();
129 drone_iterator p = connections.begin ();
130 for (drone_iterator q = connections.end (); p != q; ++p, ++mi) {
131 drone* pd = *p;
132 *mi = magnitude<double> (cx, cy, pd->cx, pd->cy);
133 }
134 }
135
set_center(float xx,float yy,int e)136 void drone::set_center (float xx, float yy, int e) {
137 cx = xx;
138 cy = yy;
139 if (frozen) set_pos (cx + mod.fm.result, cy + mod.am.result);
140 if (e) eval_conns ();
141 }
142
set_pos(float xx,float yy)143 void drone::set_pos (float xx, float yy) {
144
145 // position
146 x = xx;
147 y = yy;
148
149 // position affects velocity?
150 if (posafxvel.yes && !autorot.v.yes && !gravity && !tracking && !orbiting) {
151 double mag = magnitude (posafxvel.pt.x, posafxvel.pt.y, x, y);
152 if (mag > posafxvelt::minmag) {
153 direction (vx, vy, posafxvel.pt.x, posafxvel.pt.y, x, y);
154 vx /= mag;
155 vy /= mag;
156 posafxvel.pt.x = x;
157 posafxvel.pt.y = y;
158 }
159 }
160
161 // locate range on microtonal-keyboard
162 range = din0.find_range (x, range);
163 ::range& dr = din0.ranges[range];
164
165 // pitch position in range
166 int delta_left = x - dr.extents.left;
167 pos = delta_left * 1.0f / dr.extents.width;
168 if (pos < 0 || pos > 1.0f) ; else pos = warp_pitch (pos);
169
170 // pitch snap
171 if (snap) {
172 if (pos < din0.dinfo.snap.left)
173 note_num = 0;
174 else if (pos > din0.dinfo.snap.right)
175 note_num = 1;
176 else
177 goto normal;
178 if (note_num) {
179 pos = 1;
180 sx = dr.extents.right;
181 } else {
182 pos = 0;
183 sx = dr.extents.left;
184 }
185 } else {
186 normal:
187 note_num = -1;
188 sx = x;
189 }
190
191 calc_handle ();
192
193 update_pv = EMPLACE; // update pitch volume b4 rendering drones
194
195 }
196
calc_handle()197 void drone::calc_handle () {
198 //handle (sx - handle_size, round(y) - handle_size, sx + handle_size, round(y) + handle_size);
199 handle (sx - handle_size, y - handle_size, sx + handle_size, y + handle_size);
200 }
201
update_pitch_volume()202 void drone::update_pitch_volume () {
203
204 ::range& dr = din0.ranges[range];
205 dy = y - BOTTOM;
206 float iv = dy * 1.0f / dr.extents.height;
207 if (dy < 0) vol = -warp_vol (-iv); else vol = warp_vol (iv);
208
209 if (note_num == -1) {
210 float n0step = dr.notes[0].step, n1step = dr.notes[1].step;
211 float nstep = n0step + pos * (n1step - n0step);
212 if (nstep > 0) step = nstep;
213 } else {
214 step = dr.notes[note_num].step;
215 }
216
217 if (is == DRONE) {
218 float v = fdr.amount * mastervolume * gab.amount * vol;
219 player.set_interpolated_pitch_volume (step, v);
220 } else
221 setnoise ();
222
223 --update_pv;
224
225 }
226
227
setnoise()228 void drone::setnoise () {
229 nsr.set_samples (1.0f / step);
230 nsr.set_spread ( fabs(vol) );
231 }
232
233
234
change_bpm(mod_params & mp,float delta)235 void drone::change_bpm (mod_params& mp, float delta) {
236 mp.bv.set_bpm (mp.bv.bpm + delta);
237 }
238
change_bpm(int i,int what,float delta)239 void drone::change_bpm (int i, int what, float delta) {
240 if (what == modulator::FM) {
241 change_bpm (mod.fm, delta);
242 cons << "drone: " << i << ", FM bpm = " << mod.fm.bv.bpm << eol;
243 } else {
244 change_bpm (mod.am, delta);
245 cons << "drone: " << i << ", AM bpm = " << mod.am.bv.bpm << eol;
246 }
247 }
248
change_depth(int i,int what,float delta)249 void drone::change_depth (int i, int what, float delta) {
250 if (what == modulator::FM) {
251 mod.fm.depth += delta;
252 cons << "drone: " << i << ", FM depth = " << mod.fm.depth << eol;
253 } else {
254 mod.am.depth += delta;
255 cons << "drone: " << i << ", AM depth = " << mod.am.depth << eol;
256 }
257 }
258
clear_targets()259 void drone::clear_targets () {
260 targets.clear ();
261 cur_target = 0;
262 num_targets = 0;
263 }
264
handle_time_pass()265 void drone::handle_time_pass () {
266 double tp = ui_clk() - froze_at;
267 mod.t += tp;
268 if (autorot.v.autoflip.yes) autorot.v.tik.startt += tp;
269 if (autorot.a.autoflip.yes) autorot.a.tik.startt += tp;
270 fdr.start_time += tp;
271 if (birth != -1) birth += tp;
272 if (launcher) launch_every.startt += tp;
273 }
274
freeze()275 int drone::freeze () {
276 ++frozen;
277 froze_at = ui_clk ();
278 update_pv = drone::EMPLACE;
279 if (chuck.yes && chuckt::autoresettrails && chuck.sat) chuck.resettrail (chuck.sat);
280 return 1;
281 }
282
thaw()283 int drone::thaw () {
284 if (--frozen < 1) {
285 frozen = 0;
286 handle_time_pass ();
287 if (chuck.yes && chuckt::autoresettrails && chuck.sat) chuck.resettrail (chuck.sat);
288 return 1;
289 }
290 return 0;
291 }
292
group(std::vector<drone * > mem,int _n)293 group::group (std::vector<drone*> mem, int _n) {
294 n = _n;
295 if (n) {
296 drones.resize (n);
297 for (int i = 0; i < n; ++i) drones[i] = mem[i];
298 }
299 }
300
operator <<(std::ostream & f,drone::arrowt & aw)301 std::ostream& operator<< (std::ostream& f, drone::arrowt& aw) {
302 f << aw.u << spc << aw.v << spc << aw.t << spc << aw.cap;
303 return f;
304 }
305
operator >>(std::istream & f,drone::arrowt & aw)306 std::istream& operator>> (std::istream& f, drone::arrowt& aw) {
307 f >> aw.u >> aw.v >> aw.t >> aw.cap;
308 return f;
309 }
310
operator <<(std::ostream & f,drone::chuckt & ch)311 std::ostream& operator<< (std::ostream& f, drone::chuckt& ch) {
312 f << ch.len << spc << ch.speed << spc << ch.dir << spc << ch.ux << spc << ch.uy << spc;
313 if (ch.sun) f << ch.sun->id << spc; else f << 0 << spc;
314 if (ch.sat) f << ch.sat->id; else f << 0;
315 return f;
316 }
317
operator >>(std::istream & f,drone::chuckt & ch)318 std::istream& operator>> (std::istream& f, drone::chuckt& ch) {
319 f >> ch.len >> ch.speed >> ch.dir >> ch.ux >> ch.uy;
320 uintptr_t sun; f >> sun; ch.sun = (drone*) sun;
321 uintptr_t sat; f >> sat; ch.sat = (drone*) sat;
322 return f;
323 }
324
re(drone & p)325 void drone::chuckt::re (drone& p) {
326 if (sun) p.chuck.len = unit_vector (p.chuck.ux, p.chuck.uy, sun->cx, sun->cy, p.cx, p.cy);
327 }
328
print()329 void drone::chuckt::print () {
330 stringstream ss;
331 ss << " || Speeds: This = " << speed;
332 if (sun) {
333 ss << ", Previous = " << sun->chuck.speed;
334 } else ss << ", Previous = none";
335 if (sat) {
336 ss << ", Next = " << sat->chuck.speed;
337 } else
338 ss << ", Next = none";
339 cons << ss.str ();
340 }
341
resettrail(drone * d)342 void drone::chuckt::resettrail (drone* d) {
343 d->trail.reset ();
344 drone* sat = d->chuck.sat;
345 if (sat) sat->chuck.resettrail (sat);
346 }
347
348
operator <<(std::ostream & f,anglet & a)349 std::ostream& operator<< (std::ostream& f, anglet& a) {
350 f << a.deg;
351 return f;
352 }
353
operator >>(std::istream & f,anglet & a)354 std::istream& operator>> (std::istream& f, anglet& a) {
355 f >> a.deg;
356 a.torad ();
357 return f;
358 }
359
360 /*connect::connect (drone* _d1, drone* _d2) {
361 dirty = 1;
362 d1 = _d1;
363 d2 = _d2;
364 mag = magnitude (d1->cx, d1->cy, d2->cx, d2->cy);
365 p1.x = d1->cx; p1.y = d1->cy;
366 p2.x = d2->cx; p2.y = d2->cy;
367 align_vel ();
368 }
369
370 void connect::align_vel () {
371 unit_vector<float,float>(d1->vx, d1->vy, d1->cx, d1->cy, d2->cx, d2->cy);
372 //d2->vx = d1->vx;
373 //d2->vy = d1->vy;
374 }
375
376 int connect::eval (drone** ret) {
377 double magnew = magnitude (d1->cx, d1->cy, d2->cx, d2->cy);
378 if (magnew > mag) {
379 float ux, uy; unit_vector (ux, uy, d1->cx, d1->cy, d2->cx, d2->cy);
380 double lead = magnew - mag;
381 int d1mov = ((p1.x != d1->cx) || (p1.y != d1->cy));
382 int d2mov = ((p2.x != d2->cx) || (p2.y != d2->cy));
383 int d12mov = d1mov && d2mov;
384 if (d12mov) {
385 lead /= 2.0;
386 d1->set_center (d1->cx + lead * ux, d1->cy + lead * uy);
387 d2->set_center (d2->cx - lead * ux, d2->cy - lead * uy);
388 ret[0] = d1;
389 ret[1] = d2;
390 } else {
391 if (d1mov) {
392 d2->set_center (d2->cx - lead * ux, d2->cy - lead * uy);
393 ret[0] = d2;
394 ret[1] = 0;
395 } else if (d2mov) {
396 d1->set_center (d1->cx + lead * ux, d1->cy + lead * uy);
397 ret[0] = d1;
398 ret[1] = 0;
399 }
400 }
401 align_vel ();
402 p1.x = d1->cx; p1.y = d1->cy;
403 p2.x = d2->cx; p2.y = d2->cy;
404 dirty = 0;
405 return 1;
406 }
407 dirty = 0;
408 return 0;
409 }
410
411 void connect::draw () {
412 glBegin (GL_LINES);
413 glColor3f (d1->r, d1->g, d1->b);
414 glVertex2i (d1->cx, d1->cy);
415 glColor3f (d2->r, d2->g, d2->b);
416 glVertex2i (d2->cx, d2->cy);
417 glEnd ();
418 }*/
419