1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2026-06-29 23:38:49 +00:00

3d models in product space

This commit is contained in:
Zeno Rogue
2019-08-18 13:05:47 +02:00
parent 00f4f4fca5
commit fb0f5872c8
8 changed files with 111 additions and 56 deletions
+65 -35
View File
@@ -30,10 +30,15 @@ vector<hyperpoint> geometry_information::get_shape(hpcshape sh) {
return res;
}
hyperpoint normalize_flat(hyperpoint h) {
if(prod) return product_decompose(h).second;
return normalize(h);
}
hyperpoint get_center(const vector<hyperpoint>& vh) {
hyperpoint h = Hypc;
for(auto h1: vh) h = h + h1;
return normalize(h);
return normalize_flat(h);
}
ld zc(ld z) {
@@ -125,7 +130,7 @@ void geometry_information::add_texture(hpcshape& sh) {
vector<hyperpoint> scaleshape(const vector<hyperpoint>& vh, ld s) {
vector<hyperpoint> res;
for(hyperpoint h: vh) res.push_back(normalize(h * s + shcenter * (1-s)));
for(hyperpoint h: vh) res.push_back(normalize_flat(h * s + shcenter * (1-s)));
return res;
}
@@ -326,8 +331,8 @@ void geometry_information::make_armor_3d(hpcshape& sh, int kind) {
for(hyperpoint h: body) {
array<ld, 2> p;
p[0] = h[0] / h[3];
p[1] = h[1] / h[3];
p[0] = h[0] / h[LDIM];
p[1] = h[1] / h[LDIM];
pts[0].emplace_back(p);
}
@@ -394,8 +399,8 @@ void geometry_information::make_head_3d(hpcshape& sh) {
for(hyperpoint h: head) {
array<ld, 2> p;
p[0] = h[0] / h[3];
p[1] = h[1] / h[3];
p[0] = h[0] / h[LDIM];
p[1] = h[1] / h[LDIM];
pts[0].emplace_back(p);
}
@@ -476,6 +481,11 @@ void geometry_information::make_skeletal(hpcshape& sh, ld push) {
shift_last(-push);
}
hyperpoint yzspin(ld alpha, hyperpoint h) {
if(prod) return product::direct_exp(cspin(1, 2, alpha) * product::inverse_exp(h));
else return cspin(1, 2, alpha) * h;
}
void geometry_information::make_revolution(hpcshape& sh, int mx, ld push) {
auto body = get_shape(sh);
bshape(sh, PPR::MONSTER_BODY);
@@ -484,12 +494,12 @@ void geometry_information::make_revolution(hpcshape& sh, int mx, ld push) {
hyperpoint h0 = body[i];
hyperpoint h1 = body[(i+1) % isize(body)];
for(int s=0; s<mx; s+=step) {
hpcpush(cspin(1, 2, s * degree) * h0);
hpcpush(cspin(1, 2, s * degree) * h1);
hpcpush(cspin(1, 2, (s+step) * degree) * h0);
hpcpush(cspin(1, 2, s * degree) * h1);
hpcpush(cspin(1, 2, (s+step) * degree) * h0);
hpcpush(cspin(1, 2, (s+step) * degree) * h1);
hpcpush(yzspin(s * degree, h0));
hpcpush(yzspin(s * degree, h1));
hpcpush(yzspin((s+step) * degree, h0));
hpcpush(yzspin(s * degree, h1));
hpcpush(yzspin((s+step) * degree, h0));
hpcpush(yzspin((s+step) * degree, h1));
}
}
last->flags |= POLY_TRIANGLES;
@@ -537,7 +547,7 @@ void geometry_information::make_revolution_cut(hpcshape &sh, int each, ld push,
for(int i=0; i<n; i++) if(!stillin[i] && !stillin[lastid[i]]) lastid[i] = lastid[lastid[i]];
for(int i=0; i<n; i++) {
if(!stillin[i]) gbody[i] = normalize(gbody[lastid[i]] * (i - lastid[i]) + gbody[nextid[i]] * (nextid[i] - i));
if(!stillin[i]) gbody[i] = normalize_flat(gbody[lastid[i]] * (i - lastid[i]) + gbody[nextid[i]] * (nextid[i] - i));
}
bshape(sh, PPR::MONSTER_BODY);
@@ -551,12 +561,12 @@ void geometry_information::make_revolution_cut(hpcshape &sh, int each, ld push,
hyperpoint h1 = tbody[i1];
hyperpoint hs0 = nbody[i];
hyperpoint hs1 = nbody[i1];
hpcpush(cspin(1, 2, s * degree) * h0);
hpcpush(cspin(1, 2, s * degree) * h1);
hpcpush(cspin(1, 2, (s+step) * degree) * hs0);
hpcpush(cspin(1, 2, s * degree) * h1);
hpcpush(cspin(1, 2, (s+step) * degree) * hs0);
hpcpush(cspin(1, 2, (s+step) * degree) * hs1);
hpcpush(yzspin(s * degree, h0));
hpcpush(yzspin(s * degree, h1));
hpcpush(yzspin((s+step) * degree, hs0));
hpcpush(yzspin(s * degree, h1));
hpcpush(yzspin((s+step) * degree, hs0));
hpcpush(yzspin((s+step) * degree, hs1));
}
}
last->flags |= POLY_TRIANGLES;
@@ -600,26 +610,40 @@ void geometry_information::animate_bird(hpcshape& orig, hpcshape_animated& anima
// shift_shape(orig, BIRD);
}
EX hyperpoint forward_dir(ld x) { return prod ? point3(x, 0, 0) : xpush0(x); }
EX hyperpoint dir_to_point(hyperpoint h) { return prod ? product::direct_exp(h) : h; }
EX hyperpoint dir_setlength(hyperpoint dir, ld length) {
if(dir[0] == 0 && dir[1] == 0 && dir[2] == 0) return dir;
if(prod) return dir * (length / hypot_d(3, dir));
return rspintox(dir) * xpush0(length);
}
void geometry_information::slimetriangle(hyperpoint a, hyperpoint b, hyperpoint c, ld rad, int lev) {
dynamicval<int> d(vid.texture_step, 8);
texture_order([&] (ld x, ld y) {
ld z = 1-x-y;
ld r = scalefactor * hcrossf7 * (0 + pow(max(x,max(y,z)), .3) * 0.8);
hyperpoint h = rspintox(a*x+b*y+c*z) * xpush0(r);
ld r = scalefactor * hcrossf7 * (0 + pow(max(x,max(y,z)), .3) * 0.8) * (prod ? .5 : 1);
hyperpoint h = dir_to_point(dir_setlength(a*x+b*y+c*z, r));
hpcpush(h);
});
}
void geometry_information::balltriangle(hyperpoint a, hyperpoint b, hyperpoint c, ld rad, int lev) {
if(lev == 0) {
hpcpush(a);
hpcpush(b);
hpcpush(c);
hpcpush(dir_to_point(a));
hpcpush(dir_to_point(b));
hpcpush(dir_to_point(c));
}
else {
hyperpoint cx = rspintox(mid(a,b)) * xpush0(rad);
hyperpoint ax = rspintox(mid(b,c)) * xpush0(rad);
hyperpoint bx = rspintox(mid(c,a)) * xpush0(rad);
auto midpoint = [&] (hyperpoint h1, hyperpoint h2) {
if(prod) return dir_setlength(h1+h2, rad);
else return rspintox(mid(h1,h2)) * xpush0(rad);
};
hyperpoint cx = midpoint(a, b);
hyperpoint ax = midpoint(b, c);
hyperpoint bx = midpoint(c, a);
balltriangle(ax, bx, cx, rad, lev-1);
balltriangle(ax, bx, c , rad, lev-1);
balltriangle(ax, b , cx, rad, lev-1);
@@ -630,8 +654,8 @@ void geometry_information::balltriangle(hyperpoint a, hyperpoint b, hyperpoint c
void geometry_information::make_ball(hpcshape& sh, ld rad, int lev) {
bshape(sh, sh.prio);
sh.flags |= POLY_TRIANGLES;
hyperpoint tip = xpush0(rad);
hyperpoint atip = xpush0(-rad);
hyperpoint tip = forward_dir(rad);
hyperpoint atip = forward_dir(-rad);
ld z = 63.43 * degree;
for(int i=0; i<5; i++) {
hyperpoint a = cspin(1, 2, (72 * i ) * degree) * spin(z) * tip;
@@ -691,7 +715,13 @@ void geometry_information::make_euclidean_sky() {
);
}
/** res[0] and res[1] place H on the plane, while res[2] is the altitude */
hyperpoint psmin(hyperpoint H) {
if(prod) {
auto d = product_decompose(H);
d.second[2] = d.first;
return d.second;
}
hyperpoint res;
res[2] = asin_auto(H[2]);
ld cs = pow(cos_auto(res[2]), 2);
@@ -704,7 +734,7 @@ hyperpoint psmin(hyperpoint H) {
void geometry_information::adjust_eye(hpcshape& eye, hpcshape head, ld shift_eye, ld shift_head, int q, ld zoom) {
hyperpoint center = Hypc;
for(int i=eye.s; i<eye.e; i++) if(q == 1 || hpc[i][1] > 0) center += hpc[i];
center = normalize(center);
center = normalize_flat(center);
// center /= (eye.e - eye.s);
ld rad = 0;
for(int i=eye.s; i<eye.e; i++) if(q == 1 || hpc[i][1] > 0) rad += hdist(center, hpc[i]);
@@ -724,7 +754,7 @@ void geometry_information::adjust_eye(hpcshape& eye, hpcshape head, ld shift_eye
zmid /= isize(pss);
ld mindist = 1e9;
for(int i=0; i<isize(pss); i+=3) if(pss[i][2] < zmid || WDIM == 3) {
for(int i=0; i<isize(pss); i+=3) if(prod ? pss[i][2] > zmid : (pss[i][2] < zmid || (WDIM == 3 && !prod))) {
ld d = sqhypot_d(2, pss[i]-pscenter) + sqhypot_d(2, pss[i+1]-pscenter) + sqhypot_d(2, pss[i+2]-pscenter);
if(d < mindist) mindist = d, pos = min(min(pss[i][2], pss[i+1][2]), pss[i+2][2]), qty++;
qtyall++;
@@ -1086,10 +1116,10 @@ void geometry_information::make_3d_models() {
hyperpoint atip = xpush0(-1);
ld z = 63.43 * degree;
for(int i=0; i<5; i++) {
auto a = cspin(1, 2, (72 * i ) * degree) * spin(z) * xpush0(1);
auto b = cspin(1, 2, (72 * i-72) * degree) * spin(z) * xpush0(1);
auto c = cspin(1, 2, (72 * i+36) * degree) * spin(M_PI-z) * xpush0(1);
auto d = cspin(1, 2, (72 * i-36) * degree) * spin(M_PI-z) * xpush0(1);
auto a = cspin(1, 2, (72 * i ) * degree) * spin(z) * forward_dir(1);
auto b = cspin(1, 2, (72 * i-72) * degree) * spin(z) * forward_dir(1);
auto c = cspin(1, 2, (72 * i+36) * degree) * spin(M_PI-z) * forward_dir(1);
auto d = cspin(1, 2, (72 * i-36) * degree) * spin(M_PI-z) * forward_dir(1);
slimetriangle(tip, a, b, 1, 0);
slimetriangle(a, b, c, 1, 0);
slimetriangle(b, c, d, 1, 0);