Rev 1813 |
Rev 1828 |
Go to most recent revision |
Blame |
Compare with Previous |
Last modification |
View Log
| RSS feed
/*
* drone.cc
* DIN Is Noise is copyright (c) 2006-2021 Jagannathan Sampath
* DIN Is Noise is released under GNU Public License 2.0
* For more information, please visit https://dinisnoise.org/
*/
#include "din.h"
#include "drone.h"
#include "console.h"
#include "audio.h"
#include "utils.h"
#include "vector2d.h"
#include <math.h>
extern multi_curve drone_mod_am_crv, drone_mod_fm_crv;
extern solver warp_vol, warp_pitch;
extern const char spc;
extern void get (float& g, float& gx, float& gy, defvelaccel& dva);
extern int gethandlesize ();
extern int gettrailsize ();
extern const float TWO_PI;
void drone::setis () {
if (IS == DRONE_OR_NOISE) is = get_rand_bit (); else is = IS;
}
drone::drone (float bottom) : mod (&drone_mod_fm_crv, &drone_mod_am_crv) {
setis ();
step = vol = 0;
range = 0;
pos = 0.0f;
r = g = b = 0.5f;
cx = cy = 0;
x = y = 0;
dy = 0;
xv = x; yv = y;
xa = x; ya = y;
sx = 0;
sel = 0;
state = DEAD;
frozen = 0;
froze_at = 0;
handle_size = gethandlesize ();
trail.set (gettrailsize());
id = ++UID;
get (V, vx, vy, v0);
v_mult = 1.0f;
get (A, ax, ay, a0);
gravity = 0;
bounces = 0;
attractor = 0;
orbiting = 0;
launcher = 0;
tracking = 0;
tracked_drone = 0;
dpm = 60;
++ref;
launched_by = 0;
reincarnate = 0;
switch (ARE) {
case IMMORTAL:
birth = -1;
break;
case MORTAL:
birth = ui_clk ();
break;
case REINCARNATE:
birth = ui_clk ();
reincarnate = 1;
break;
}
life = LIFETIME;
insert = INSERTTIME;
target = 0;
cur_target = 0;
num_targets = 0;
update_pv = UNSET;
snap = 0;
nconn = 0;
type = CHAIN;
gab.set (1.0f, 0.0f, 0, 1.0f);
tovol = 0.0f;
finl = 0;
note_num = -1;
}
drone::~drone () {
--ref;
}
void drone::move_center () {
cx += (x - xi);
cy += (y - yi);
}
drone* drone::eval_conns () {
if (nconn) {
int n = 0;
proc_conn [this] = true;
list<double>::iterator mi = mags.begin();
drone_iterator p = connections.begin ();
drone* c0 = *p;
for (drone_iterator q = connections.end (); p != q; ++p, ++mi) {
drone* pdc = *p;
if (proc_conn[pdc] == false) {
proc_conn [pdc] = true;
drone& dc = *pdc;
double now = magnitude (cx, cy, dc.cx, dc.cy);
double org = *mi;
if (now > org) {
double lead = STIFFNESS * (now - org);
float ux, uy; unit_vector<float, int> (ux, uy, dc.cx, dc.cy, cx, cy);
dc.set_center (dc.cx + lead * ux, dc.cy + lead * uy);
++n;
}
}
}
if (n) return this; else return c0;
}
return 0;
}
void drone::remagconns () {
list<double>::iterator mi = mags.begin();
drone_iterator p = connections.begin ();
for (drone_iterator q = connections.end (); p != q; ++p, ++mi) {
drone* pd = *p;
*mi = magnitude<double> (cx, cy, pd->cx, pd->cy);
}
}
void drone::set_center (float xx, float yy, int e) {
cx = xx;
cy = yy;
if (frozen) set_pos (cx + mod.fm.result, cy + mod.am.result);
if (e) eval_conns ();
}
void drone::set_pos (float xx, float yy) {
// position
x = xx;
y = yy;
// position affects velocity?
if (posafxvel.yes && !autorot.v.yes && !gravity && !tracking && !orbiting) {
double mag = magnitude (posafxvel.pt.x, posafxvel.pt.y, x, y);
if (mag > posafxvelt::minmag) {
direction (vx, vy, posafxvel.pt.x, posafxvel.pt.y, x, y);
vx /= mag;
vy /= mag;
posafxvel.pt.x = x;
posafxvel.pt.y = y;
}
}
// locate range on microtonal-keyboard
range = din0.find_range (x, range);
::range& dr = din0.ranges[range];
// pitch position in range
int delta_left = x - dr.extents.left;
pos = delta_left * 1.0f / dr.extents.width;
if (pos < 0 || pos > 1.0f) ; else pos = warp_pitch (pos);
// pitch snap
if (snap) {
if (pos < din0.dinfo.snap.left)
note_num = 0;
else if (pos > din0.dinfo.snap.right)
note_num = 1;
else
goto normal;
if (note_num) {
pos = 1;
sx = dr.extents.right;
} else {
pos = 0;
sx = dr.extents.left;
}
} else {
normal:
note_num = -1;
sx = x;
}
calc_handle ();
update_pv = EMPLACE; // update pitch volume b4 rendering drones
}
void drone::calc_handle () {
//handle (sx - handle_size, round(y) - handle_size, sx + handle_size, round(y) + handle_size);
handle (sx - handle_size, y - handle_size, sx + handle_size, y + handle_size);
}
void drone::update_pitch_volume () {
::range& dr = din0.ranges[range];
dy = y - BOTTOM;
float iv = dy * 1.0f / dr.extents.height;
if (dy < 0) vol = -warp_vol (-iv); else vol = warp_vol (iv);
if (note_num == -1) {
float n0step = dr.notes[0].step, n1step = dr.notes[1].step;
float nstep = n0step + pos * (n1step - n0step);
if (nstep > 0) step = nstep;
} else {
step = dr.notes[note_num].step;
}
if (is == DRONE) {
float v = fdr.amount * mastervolume * gab.amount * vol;
player.set_interpolated_pitch_volume (step, v);
} else
setnoise ();
--update_pv;
}
void drone::setnoise () {
nsr.set_samples (1.0f / step);
nsr.set_spread ( fabs(vol) );
}
void drone::change_bpm (mod_params& mp, float delta) {
mp.bv.set_bpm (mp.bv.bpm + delta);
}
void drone::change_bpm (int i, int what, float delta) {
if (what == modulator::FM) {
change_bpm (mod.fm, delta);
cons << "drone: " << i << ", FM bpm = " << mod.fm.bv.bpm << eol;
} else {
change_bpm (mod.am, delta);
cons << "drone: " << i << ", AM bpm = " << mod.am.bv.bpm << eol;
}
}
void drone::change_depth (int i, int what, float delta) {
if (what == modulator::FM) {
mod.fm.depth += delta;
cons << "drone: " << i << ", FM depth = " << mod.fm.depth << eol;
} else {
mod.am.depth += delta;
cons << "drone: " << i << ", AM depth = " << mod.am.depth << eol;
}
}
void drone::clear_targets () {
targets.clear ();
cur_target = 0;
num_targets = 0;
}
void drone::handle_time_pass () {
double tp = ui_clk() - froze_at;
mod.t += tp;
fdr.start_time += tp;
if (birth != -1) birth += tp;
if (launcher) launch_every.startt += tp;
}
int drone::freeze () {
++frozen;
froze_at = ui_clk ();
update_pv = drone::EMPLACE;
if (chuck.yes && chuckt::autoresettrails && chuck.sat) chuck.resettrail (chuck.sat);
return 1;
}
int drone::thaw () {
if (--frozen < 1) {
frozen = 0;
handle_time_pass ();
if (chuck.yes && chuckt::autoresettrails && chuck.sat) chuck.resettrail (chuck.sat);
return 1;
}
return 0;
}
group::group (std::vector<drone*> mem, int _n) {
n = _n;
if (n) {
drones.resize (n);
for (int i = 0; i < n; ++i) drones[i] = mem[i];
}
}
std::ostream& operator<< (std::ostream& f, drone::arrowt& aw) {
f << aw.u << spc << aw.v << spc << aw.t << spc << aw.cap;
return f;
}
std::istream& operator>> (std::istream& f, drone::arrowt& aw) {
f >> aw.u >> aw.v >> aw.t >> aw.cap;
return f;
}
std::ostream& operator<< (std::ostream& f, drone::chuckt& ch) {
f << ch.len << spc << ch.speed << spc << ch.dir << spc << ch.ux << spc << ch.uy << spc;
if (ch.sun) f << ch.sun->id << spc; else f << 0 << spc;
if (ch.sat) f << ch.sat->id; else f << 0;
return f;
}
std::istream& operator>> (std::istream& f, drone::chuckt& ch) {
f >> ch.len >> ch.speed >> ch.dir >> ch.ux >> ch.uy;
uintptr_t sun; f >> sun; ch.sun = (drone*) sun;
uintptr_t sat; f >> sat; ch.sat = (drone*) sat;
return f;
}
std::istream& operator>> (std::istream& f, defvelaccel& dva) {
f >> dva.mag >> dva.dir >> dva.neg >> dva.rndrot >> dva.clock >> dva.anticlock;
f >> dva.autos.rot.yes >> dva.autos.rot.dir >> dva.autos.rot.mov >> dva.autos.rot.rpm >> dva.autos.rot.dps >> dva.autos.rot.tps;
f >> dva.autos.flip.yes >> dva.autos.flip.deg;
dva.rotrd.set (-dva.clock.rad, dva.anticlock.rad);
return f;
}
std::ostream& operator<< (std::ostream& f, defvelaccel& dva) {
f << dva.mag << spc << dva.dir << spc << dva.neg << spc << dva.rndrot << spc << dva.clock << spc << dva.anticlock << spc;
f << dva.autos.rot.yes << spc << dva.autos.rot.dir << spc << dva.autos.rot.mov << spc << dva.autos.rot.rpm << spc << dva.autos.rot.dps << spc << dva.autos.rot.tps << spc;
f << dva.autos.flip.yes << spc << dva.autos.flip.deg;
return f;
}
std::istream& operator>> (std::istream& f, valt& mag) {
f >> mag.val >> mag.rndrd >> mag.rd;
return f;
}
std::ostream& operator<< (std::ostream& f, valt& mag) {
f << mag.val << spc << mag.rndrd << spc << mag.rd;
return f;
}
void drone::chuckt::re (drone& p) {
if (sun) p.chuck.len = unit_vector (p.chuck.ux, p.chuck.uy, sun->cx, sun->cy, p.cx, p.cy);
}
void drone::chuckt::print () {
stringstream ss;
ss << " || Speeds: This = " << speed;
if (sun) {
ss << ", Previous = " << sun->chuck.speed;
} else ss << ", Previous = none";
if (sat) {
ss << ", Next = " << sat->chuck.speed;
} else
ss << ", Next = none";
cons << ss.str ();
}
void drone::chuckt::resettrail (drone* d) {
d->trail.reset ();
drone* sat = d->chuck.sat;
if (sat) sat->chuck.resettrail (sat);
}
defvelaccel::defvelaccel (const std::string& n) : name (n) {
dir = VERTICAL;
neg = 0;
rndrot = 0;
clock = anticlock = 0.0f;
}
void defvelaccel::setrotrd () {
rotrd.set (-clock.rad, anticlock.rad);
}
std::ostream& operator<< (std::ostream& f, anglet& a) {
f << a.deg;
return f;
}
std::istream& operator>> (std::istream& f, anglet& a) {
f >> a.deg;
a.torad ();
return f;
}
autorotator::autorotator (defvelaccel& d) : autoflip(d) {
yes = d.autos.rot.yes;
int i = 0;
if (d.autos.rot.dir == RANDOM) i = get_rand_bit (); else i = d.autos.rot.dir;
static const int dirs [] = {-1, 1};
dir = dirs[i];
if (d.autos.rot.mov == RANDOM)
mov = get_rand_bit ();
else
mov = d.autos.rot.mov;
if (mov == SMOOTH) {
set_rpm (d.autos.rot.rpm());
deg = 6.0f;
tps = 1.0f;
}
else {
setdeg (d.autos.rot.dps());
settps (d.autos.rot.tps());
rpm = 0.0f;
}
}
void autorotator::set_rpm (float r) {
if (r > 0) {
rpm = r;
angle.persec = TWO_PI * r / 60.0f;
} else {
rpm = 0;
angle.persec = 0.0f;
}
}
void autorotator::chgdeg (float d) {
setdeg (deg + d);
}
void autorotator::chgtps (float t) {
settps (tps + t);
setdeg (deg);
}
void autorotator::calc (double dt) {
if (mov == SMOOTH)
angle.theta = dt * angle.persec;
else {
if (tik (ui_clk())) angle.theta = tik.triggert * angle.persec; else angle.theta = 0.0f;
}
if (autoflip.yes) autoflip.calc (angle.theta, dir);
angle.theta *= dir;
}
void autoflipt::calc (float theta, int& dir) {
total += theta;
if (total > angle.rad) {
dir = -dir;
total = 0.0f;
}
}
autoflipt::autoflipt (defvelaccel& d) {
yes = d.autos.flip.yes;
angle = d.autos.flip.deg();
total = 0.0f;
}
using namespace std;
istream& operator>> (istream& file, autorotator& ar) {
file >> ar.yes >> ar.dir >> ar.rpm >> ar.mov >> ar.deg >> ar.tps >> ar.autoflip;
if (ar.mov == autorotator::SMOOTH)
ar.set_rpm (ar.rpm);
else {
ar.setdeg (ar.deg);
ar.settps (ar.tps);
}
return file;
}
ostream& operator<< (ostream& file, autorotator& ar) {
file << ar.yes << spc << ar.dir << spc << ar.rpm << spc << ar.mov << spc << ar.deg << spc << ar.tps << spc << ar.autoflip;
return file;
}
istream& operator>> (istream& file, autoflipt& af) {
float d;
file >> af.yes >> d >> af.total;
af.angle = d;
return file;
}
ostream& operator<< (ostream& file, autoflipt& af) {
file << af.yes << spc << af.angle.deg << spc << af.total;
return file;
}
/*connect::connect (drone* _d1, drone* _d2) {
dirty = 1;
d1 = _d1;
d2 = _d2;
mag = magnitude (d1->cx, d1->cy, d2->cx, d2->cy);
p1.x = d1->cx; p1.y = d1->cy;
p2.x = d2->cx; p2.y = d2->cy;
align_vel ();
}
void connect::align_vel () {
unit_vector<float,float>(d1->vx, d1->vy, d1->cx, d1->cy, d2->cx, d2->cy);
//d2->vx = d1->vx;
//d2->vy = d1->vy;
}
int connect::eval (drone** ret) {
double magnew = magnitude (d1->cx, d1->cy, d2->cx, d2->cy);
if (magnew > mag) {
float ux, uy; unit_vector (ux, uy, d1->cx, d1->cy, d2->cx, d2->cy);
double lead = magnew - mag;
int d1mov = ((p1.x != d1->cx) || (p1.y != d1->cy));
int d2mov = ((p2.x != d2->cx) || (p2.y != d2->cy));
int d12mov = d1mov && d2mov;
if (d12mov) {
lead /= 2.0;
d1->set_center (d1->cx + lead * ux, d1->cy + lead * uy);
d2->set_center (d2->cx - lead * ux, d2->cy - lead * uy);
ret[0] = d1;
ret[1] = d2;
} else {
if (d1mov) {
d2->set_center (d2->cx - lead * ux, d2->cy - lead * uy);
ret[0] = d2;
ret[1] = 0;
} else if (d2mov) {
d1->set_center (d1->cx + lead * ux, d1->cy + lead * uy);
ret[0] = d1;
ret[1] = 0;
}
}
align_vel ();
p1.x = d1->cx; p1.y = d1->cy;
p2.x = d2->cx; p2.y = d2->cy;
dirty = 0;
return 1;
}
dirty = 0;
return 0;
}
void connect::draw () {
glBegin (GL_LINES);
glColor3f (d1->r, d1->g, d1->b);
glVertex2i (d1->cx, d1->cy);
glColor3f (d2->r, d2->g, d2->b);
glVertex2i (d2->cx, d2->cy);
glEnd ();
}*/