1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2024-11-30 15:39:54 +00:00

flocking:: nonisotropic

This commit is contained in:
Zeno Rogue 2020-03-20 19:49:59 +01:00
parent 8503104470
commit 7449a48198

View File

@ -16,6 +16,8 @@
// press 'o' when flocking active to change the parameters. // press 'o' when flocking active to change the parameters.
// (does not yet work in product geometries)
#ifdef USE_THREADS #ifdef USE_THREADS
#include <thread> #include <thread>
int threads = 1; int threads = 1;
@ -99,7 +101,7 @@ namespace flocking {
for(int i=0; i<isize(cl.lst); i++) { for(int i=0; i<isize(cl.lst); i++) {
cell *c2 = cl.lst[i]; cell *c2 = cl.lst[i];
transmatrix T = calc_relative_matrix(c2, c1, C0); transmatrix T = calc_relative_matrix(c2, c1, C0);
if(hdist0(tC0(T)) <= check_range) { if(hypot_d(WDIM, inverse_exp(tC0(T), iTable, false)) <= check_range) {
relmatrices[c1][c2] = T; relmatrices[c1][c2] = T;
forCellEx(c3, c2) cl.add(c3); forCellEx(c3, c2) cl.add(c3);
} }
@ -110,7 +112,7 @@ namespace flocking {
for(int i=0; i<N; i++) { for(int i=0; i<N; i++) {
vertexdata& vd = vdata[i]; vertexdata& vd = vdata[i];
// set initial base and at to random cell and random position there // set initial base and at to random cell and random position there
createViz(i, v[hrand(isize(v))], spin(hrand(100)) * xpush(hrand(100) / 200.)); createViz(i, v[hrand(isize(v))], random_spin() * xpush(hrand(100) / 200.));
vd.name = its(i+1); vd.name = its(i+1);
vd.cp = dftcolor; vd.cp = dftcolor;
vd.cp.color2 = ((hrand(0x1000000) << 8) + 0xFF) | 0x808080FF; vd.cp.color2 = ((hrand(0x1000000) << 8) + 0xFF) | 0x808080FF;
@ -133,6 +135,7 @@ namespace flocking {
ld d = delta / 1000.; ld d = delta / 1000.;
int N = isize(vdata); int N = isize(vdata);
vector<transmatrix> pats(N); vector<transmatrix> pats(N);
vector<transmatrix> oris(N);
vector<ld> vels(N); vector<ld> vels(N);
using shmup::monster; using shmup::monster;
@ -146,11 +149,20 @@ namespace flocking {
lines.clear(); lines.clear();
parallelize(N, [&monsat, &d, &vels, &pats] (int a, int b) { for(int i=a; i<b; i++) { parallelize(N, [&monsat, &d, &vels, &pats, &oris] (int a, int b) { for(int i=a; i<b; i++) {
vertexdata& vd = vdata[i]; vertexdata& vd = vdata[i];
auto m = vd.m; auto m = vd.m;
transmatrix I = inverse(m->at); transmatrix I, Rot;
if(nonisotropic) {
I = gpushxto0(tC0(m->at));
Rot = inverse(I * m->at);
}
else {
I = inverse(m->at);
Rot = Id;
}
// we do all the computations here in the frame of reference // we do all the computations here in the frame of reference
// where m is at (0,0,1) and its velocity is (m->vel,0,0) // where m is at (0,0,1) and its velocity is (m->vel,0,0)
@ -175,11 +187,11 @@ namespace flocking {
// at2 is like m2->at but relative to m->at // at2 is like m2->at but relative to m->at
// m2's position relative to m (tC0 means *(0,0,1)) // m2's position relative to m (tC0 means *(0,0,1))
hyperpoint ac = tC0(at2); hyperpoint ac = inverse_exp(tC0(at2), iTable, false);
if(nonisotropic) ac = Rot * ac;
// distance and azimuth to m2 // distance and azimuth to m2
ld di = hdist0(ac); ld di = hypot_d(WDIM, ac);
transmatrix alphaspin = rspintox(ac); // spin(-atan2(ac));
color_t col = 0; color_t col = 0;
@ -187,22 +199,22 @@ namespace flocking {
// we need to transfer m2's velocity vector to m's position // we need to transfer m2's velocity vector to m's position
// this is done by applying an isometry which sends m2 to m1 // this is done by applying an isometry which sends m2 to m1
// and maps the straight line on which m1 and m2 are to itself // and maps the straight line on which m1 and m2 are to itself
align += gpushxto0(ac) * at2 * hpxyz(vel2, 0, 0);
// note: in nonisotropic it is not clear whether we should
// use gpushxto0, or parallel transport along the shortest geodesic
align += gpushxto0(tC0(at2)) * at2 * hpxyz(vel2, 0, 0);
align_count++; align_count++;
col |= 0xFF0040; col |= 0xFF0040;
} }
if(di < coh_range) { if(di < coh_range) {
// azimuthal equidistant projection of ac coh += tangent_length(ac, di);
// (thus the cohesion force pushes us towards the
// average of azimuthal equidistant projections)
coh += alphaspin * hpxyz(di, 0, 0);
coh_count++; coh_count++;
col |= 0xFF40; col |= 0xFF40;
} }
if(di < sep_range && di > 0) { if(di < sep_range && di > 0) {
sep -= alphaspin * hpxyz(1 / di, 0, 0); sep -= tangent_length(ac, 1 / di);
sep_count++; sep_count++;
col |= 0xFF000040; col |= 0xFF000040;
} }
@ -228,8 +240,13 @@ namespace flocking {
vels[i] = max_speed; vels[i] = max_speed;
} }
pats[i] = m->at * alphaspin * xpush(vels[i] * d); pats[i] = m->at;
oris[i] = m->ori;
rotate_object(pats[i], oris[i], alphaspin);
apply_parallel_transport(pats[i], oris[i], xtangent(vels[i] * d));
fixmatrix(pats[i]); fixmatrix(pats[i]);
} return 0; }); } return 0; });
for(int i=0; i<N; i++) { for(int i=0; i<N; i++) {
@ -237,6 +254,7 @@ namespace flocking {
auto m = vd.m; auto m = vd.m;
// these two functions compute new base and at, based on pats[i] // these two functions compute new base and at, based on pats[i]
m->at = pats[i]; m->at = pats[i];
m->ori = oris[i];
virtualRebase(m); virtualRebase(m);
m->vel = vels[i]; m->vel = vels[i];
} }