mirror of
https://github.com/zenorogue/hyperrogue.git
synced 2024-12-24 17:10:36 +00:00
primitive-based rendering of the Berger sphere (very poor)
This commit is contained in:
parent
2dff2df4fe
commit
94cac21716
12
config.cpp
12
config.cpp
@ -673,6 +673,8 @@ EX void initConfig() {
|
||||
addsaver(bright, "bright");
|
||||
addsaver(cblind, "cblind");
|
||||
|
||||
addsaver(berger_limit, "berger_limit");
|
||||
|
||||
addsaverenum(centering, "centering");
|
||||
|
||||
callhooks(hooks_configfile);
|
||||
@ -1729,6 +1731,16 @@ EX void show3D() {
|
||||
});
|
||||
}
|
||||
|
||||
if(WDIM == 3 && sphere && stretch::factor) {
|
||||
dialog::addItem(XLAT("Berger sphere limit"), berger_limit);
|
||||
dialog::add_action([] () {
|
||||
dialog::editNumber(berger_limit, 0, 10, 1, 2, "",
|
||||
XLAT("Primitive-based rendering of Berger sphere is currently very slow and low quality. "
|
||||
"Here you can choose how many images to draw.")
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#if CAP_RAY
|
||||
if(GDIM == 3) {
|
||||
dialog::addItem(XLAT("configure raycasting"), 'A');
|
||||
|
84
drawing.cpp
84
drawing.cpp
@ -1255,6 +1255,80 @@ void draw_s2xe0(dqi_poly *p) {
|
||||
#endif
|
||||
EX }
|
||||
|
||||
EX int berger_limit = 2;
|
||||
|
||||
void draw_stretch(dqi_poly *p) {
|
||||
|
||||
if(!(p->flags & POLY_TRIANGLES)) return;
|
||||
|
||||
dqi_poly npoly = *p;
|
||||
|
||||
npoly.offset = 0;
|
||||
npoly.tab = &glcoords;
|
||||
npoly.V = Id;
|
||||
npoly.flags &= ~(POLY_INVERSE | POLY_FORCE_INVERTED);
|
||||
|
||||
transmatrix T2 = stretch::translate( tC0(inverse(View)) );
|
||||
transmatrix U = View * T2;
|
||||
|
||||
transmatrix iUV = inverse(U) * p->V;
|
||||
|
||||
vector<hyperpoint> hs;
|
||||
vector<hyperpoint> ths;
|
||||
hs.resize(p->cnt);
|
||||
ths.resize(p->cnt);
|
||||
for(int i=0; i<p->cnt; i++)
|
||||
hs[i] = iUV * glhr::gltopoint( (*p->tab)[p->offset+i] );
|
||||
|
||||
vector<vector<hyperpoint> > results;
|
||||
results.resize(p->cnt);
|
||||
|
||||
auto& stinf = s2xe::stinf;
|
||||
|
||||
if(p->tinf) {
|
||||
npoly.tinf = &stinf;
|
||||
npoly.offset_texture = 0;
|
||||
stinf.texture_id = p->tinf->texture_id;
|
||||
stinf.tvertices.clear();
|
||||
}
|
||||
else {
|
||||
npoly.tinf = NULL;
|
||||
}
|
||||
npoly.V = Id;
|
||||
set_width(1);
|
||||
glcoords.clear();
|
||||
|
||||
for(int i=0; i<p->cnt; i++) results[i] = stretch::inverse_exp_all(hs[i], berger_limit);
|
||||
|
||||
for(int i=0; i<p->cnt; i+=3) {
|
||||
auto &la = results[i];
|
||||
auto &lb = results[i+1];
|
||||
auto &lc = results[i+2];
|
||||
|
||||
int ia = 0, ib = 0, ic = 0;
|
||||
|
||||
auto test = [] (hyperpoint a, hyperpoint b) -> bool {
|
||||
return sqhypot_d(3, a-b) < 2;
|
||||
};
|
||||
|
||||
for(auto& ha: la) for(auto& hb: lb) if(test(ha, hb))
|
||||
for(auto& hc: lc) if(test(ha, hc) && test(hb, hc)) {
|
||||
|
||||
glcoords.push_back(glhr::pointtogl(U * ha));
|
||||
glcoords.push_back(glhr::pointtogl(U * hb));
|
||||
glcoords.push_back(glhr::pointtogl(U * hc));
|
||||
if(p->tinf)
|
||||
for(int j=0; j<3; j++)
|
||||
stinf.tvertices.push_back(p->tinf->tvertices[p->offset_texture+i+j]);
|
||||
ia++; ib++; ic++;
|
||||
}
|
||||
}
|
||||
|
||||
npoly.cnt = isize(glcoords);
|
||||
|
||||
npoly.gldraw();
|
||||
}
|
||||
|
||||
EX namespace ods {
|
||||
#if CAP_ODS
|
||||
|
||||
@ -1522,6 +1596,11 @@ void dqi_poly::draw() {
|
||||
return;
|
||||
} */
|
||||
|
||||
if(vid.usingGL && (current_display->set_all(global_projection), get_shader_flags() & SF_DIRECT) && sphere && (stretch::factor || ray::in_use)) {
|
||||
draw_stretch(this);
|
||||
return;
|
||||
}
|
||||
|
||||
#if CAP_GL
|
||||
if(vid.usingGL && (current_display->set_all(global_projection), get_shader_flags() & SF_DIRECT)) {
|
||||
if(sl2 && pmodel == mdGeodesic && hybrid::csteps) {
|
||||
@ -1997,14 +2076,11 @@ EX void reverse_transparent_walls() {
|
||||
|
||||
EX void draw_main() {
|
||||
DEBBI(DF_GRAPH, ("draw_main"));
|
||||
if(sphere && GDIM == 3 && pmodel == mdPerspective) {
|
||||
if(sphere && GDIM == 3 && pmodel == mdPerspective && !stretch::in() && !ray::in_use) {
|
||||
|
||||
if(ray::in_use && !ray::comparison_mode) {
|
||||
ray::cast();
|
||||
reset_projection();
|
||||
/* currently incompatible with primitive-based renderer */
|
||||
/* also not implemented in stretch */
|
||||
if(stretch::factor) return;
|
||||
}
|
||||
|
||||
#if CAP_GL
|
||||
|
@ -1573,10 +1573,13 @@ EX void enable_flat_model() {
|
||||
|
||||
#if HDR
|
||||
/** \brief enable the 'flat' model for drawing HUD. Use RAII so it will be switched back later */
|
||||
namespace stretch { extern ld factor; }
|
||||
|
||||
struct flat_model_enabler {
|
||||
projection_configuration bak;
|
||||
flat_model_enabler() { bak = pconf; enable_flat_model(); }
|
||||
~flat_model_enabler() { pconf = bak; calcparam(); }
|
||||
ld sf;
|
||||
flat_model_enabler() { bak = pconf; sf = stretch::factor; stretch::factor = 0; enable_flat_model(); }
|
||||
~flat_model_enabler() { pconf = bak; stretch::factor = sf; calcparam(); }
|
||||
};
|
||||
#endif
|
||||
|
||||
|
123
nonisotropic.cpp
123
nonisotropic.cpp
@ -2404,6 +2404,129 @@ EX namespace stretch {
|
||||
h = itranslate(at) * h;
|
||||
return h[0] * h[0] + h[1] * h[1] + h[2] * h[2];
|
||||
}
|
||||
|
||||
EX vector<hyperpoint> inverse_exp_all(hyperpoint h, int generations) {
|
||||
|
||||
vector<hyperpoint> res;
|
||||
|
||||
if(stretch::factor == 0) {
|
||||
ld d = hypot_d(3, h);
|
||||
if(h[3] >= 1 || h[3] <= -1|| d == 0) return res;
|
||||
ld a = acos(h[3]);
|
||||
|
||||
res.push_back(point31(h[0] * a / d, h[1] * a / d, h[2] * a / d));
|
||||
|
||||
a = a - 2 * M_PI;
|
||||
|
||||
res.push_back(point31(h[0] * a / d, h[1] * a / d, h[2] * a / d));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
ld xy = hypot_d(2, h);
|
||||
ld SV = stretch::not_squared();
|
||||
|
||||
ld base_min_a = asin(xy);
|
||||
ld base_max_a = M_PI - base_min_a;
|
||||
|
||||
ld seek = M_PI/2-atan2(h[3], h[2]);
|
||||
|
||||
auto ang = [&] (ld a) {
|
||||
ld rp = xy / sin(a);
|
||||
ld co = abs(rp) >= 1 ? 0 : sqrt(1-rp*rp);
|
||||
|
||||
return atan2(co * sin(a), cos(a)) - co * (1 - 1/SV/SV) * a;
|
||||
|
||||
// while(a0 > M_PI) a0 -= 2 * M_PI;
|
||||
// while(a0 < -M_PI) a0 += 2 * M_PI;
|
||||
};
|
||||
|
||||
for(int shift=-generations; shift<generations; shift++) {
|
||||
ld min_a = base_min_a + M_PI * shift;
|
||||
ld max_a = base_max_a + M_PI * shift;
|
||||
|
||||
ld ang_min = ang(min_a);
|
||||
ld ang_max = ang(max_a);
|
||||
|
||||
for(int mi=0; mi<2; mi++) {
|
||||
// 0 : minimum, 1 : maximum
|
||||
ld tl = min_a, tr = max_a;
|
||||
for(int it=0; it<20; it++) {
|
||||
ld t1 = tl * .51 + tr * .49;
|
||||
ld t2 = tl * .49 + tr * .51;
|
||||
if((ang(t1) < ang(t2)) == mi)
|
||||
tr = t1;
|
||||
else
|
||||
tl = t2;
|
||||
}
|
||||
ld extreme = (tl + tr) / 2;
|
||||
ld ang_extreme = ang(extreme);
|
||||
for(int t=0; t<2; t++) {
|
||||
ld mmin = t == 0 ? min_a : extreme;
|
||||
ld mmax = t == 0 ? extreme : max_a;
|
||||
ld vmin = t == 0 ? ang_min : ang_extreme;
|
||||
ld vmax = t == 0 ? ang_extreme : ang_max;
|
||||
|
||||
// make it increasing
|
||||
if(t != mi) swap(mmin, mmax), swap(vmin, vmax);
|
||||
|
||||
// println(hlog, "*** ", mi, t, " ** ", tie(min_a, ang_min), tie(extreme, ang_extreme), tie(max_a, ang_max), " -> ", vmin, " to ", vmax);
|
||||
|
||||
int cmin = ceil((vmin - seek) / 2 / M_PI);
|
||||
int cmax = floor((vmax - seek) / 2 / M_PI);
|
||||
for(int c = cmin; c <= cmax; c++) {
|
||||
ld cseek = seek + c * 2 * M_PI;
|
||||
|
||||
for(int it=0; it<40; it++) {
|
||||
|
||||
ld a = (mmin + mmax) / 2;
|
||||
|
||||
ld cros = ang(a);
|
||||
if(cros > cseek) mmax = a; else mmin = a;
|
||||
}
|
||||
|
||||
ld a = (mmin + mmax) / 2;
|
||||
|
||||
ld r = asin_clamp( xy / sin(a) );
|
||||
|
||||
ld z_part = 1;
|
||||
ld x_part = SV * tan(r);
|
||||
|
||||
ld db = hypot(x_part, z_part);
|
||||
x_part /= db;
|
||||
z_part /= db;
|
||||
|
||||
ld alpha = atan2(-h[1], h[0]);
|
||||
|
||||
ld z = cos(r) * (1 - 1/SV/SV);
|
||||
ld u = z * a;
|
||||
|
||||
ld r_angle = alpha + u;
|
||||
|
||||
ld len = a * hypot(sin_auto(r), cos_auto(r)/SV);
|
||||
|
||||
auto answer = point3(cos(r_angle) * x_part * len, -sin(r_angle) * x_part * len, z_part * len);
|
||||
|
||||
// int id = (shift << 10) + (mi << 9) + (t << 8) + c;
|
||||
|
||||
/*
|
||||
auto f = formula_exp(answer);
|
||||
|
||||
ld err = sqhypot_d(4, f - h);
|
||||
|
||||
println(hlog, "************************* ", answer, ": error = ", err, " id = ", id, " params = ", tie(shift, mi, t, c));
|
||||
*/
|
||||
|
||||
res.emplace_back(answer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
EX }
|
||||
|
||||
EX namespace nisot {
|
||||
|
@ -248,7 +248,7 @@ shared_ptr<glhr::GLprogram> write_shader(flagtype shader_flags) {
|
||||
shader_flags |= SF_PERS3 | SF_DIRECT;
|
||||
if(hyperbolic)
|
||||
distfun = "acosh(t[3])", treset = true;
|
||||
else if(euclid || nonisotropic)
|
||||
else if(euclid || nonisotropic || stretch::in() || (sphere && ray::in_use))
|
||||
distfun = "length(t.xyz)", treset = true;
|
||||
else {
|
||||
if(spherephase & 4) coordinator += "t = -t;\n";
|
||||
|
Loading…
Reference in New Issue
Block a user