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(bright, "bright");
|
||||||
addsaver(cblind, "cblind");
|
addsaver(cblind, "cblind");
|
||||||
|
|
||||||
|
addsaver(berger_limit, "berger_limit");
|
||||||
|
|
||||||
addsaverenum(centering, "centering");
|
addsaverenum(centering, "centering");
|
||||||
|
|
||||||
callhooks(hooks_configfile);
|
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 CAP_RAY
|
||||||
if(GDIM == 3) {
|
if(GDIM == 3) {
|
||||||
dialog::addItem(XLAT("configure raycasting"), 'A');
|
dialog::addItem(XLAT("configure raycasting"), 'A');
|
||||||
|
|
84
drawing.cpp
84
drawing.cpp
|
@ -1255,6 +1255,80 @@ void draw_s2xe0(dqi_poly *p) {
|
||||||
#endif
|
#endif
|
||||||
EX }
|
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 {
|
EX namespace ods {
|
||||||
#if CAP_ODS
|
#if CAP_ODS
|
||||||
|
|
||||||
|
@ -1522,6 +1596,11 @@ void dqi_poly::draw() {
|
||||||
return;
|
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 CAP_GL
|
||||||
if(vid.usingGL && (current_display->set_all(global_projection), get_shader_flags() & SF_DIRECT)) {
|
if(vid.usingGL && (current_display->set_all(global_projection), get_shader_flags() & SF_DIRECT)) {
|
||||||
if(sl2 && pmodel == mdGeodesic && hybrid::csteps) {
|
if(sl2 && pmodel == mdGeodesic && hybrid::csteps) {
|
||||||
|
@ -1997,14 +2076,11 @@ EX void reverse_transparent_walls() {
|
||||||
|
|
||||||
EX void draw_main() {
|
EX void draw_main() {
|
||||||
DEBBI(DF_GRAPH, ("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) {
|
if(ray::in_use && !ray::comparison_mode) {
|
||||||
ray::cast();
|
ray::cast();
|
||||||
reset_projection();
|
reset_projection();
|
||||||
/* currently incompatible with primitive-based renderer */
|
|
||||||
/* also not implemented in stretch */
|
|
||||||
if(stretch::factor) return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if CAP_GL
|
#if CAP_GL
|
||||||
|
|
|
@ -1573,10 +1573,13 @@ EX void enable_flat_model() {
|
||||||
|
|
||||||
#if HDR
|
#if HDR
|
||||||
/** \brief enable the 'flat' model for drawing HUD. Use RAII so it will be switched back later */
|
/** \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 {
|
struct flat_model_enabler {
|
||||||
projection_configuration bak;
|
projection_configuration bak;
|
||||||
flat_model_enabler() { bak = pconf; enable_flat_model(); }
|
ld sf;
|
||||||
~flat_model_enabler() { pconf = bak; calcparam(); }
|
flat_model_enabler() { bak = pconf; sf = stretch::factor; stretch::factor = 0; enable_flat_model(); }
|
||||||
|
~flat_model_enabler() { pconf = bak; stretch::factor = sf; calcparam(); }
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
123
nonisotropic.cpp
123
nonisotropic.cpp
|
@ -2404,6 +2404,129 @@ EX namespace stretch {
|
||||||
h = itranslate(at) * h;
|
h = itranslate(at) * h;
|
||||||
return h[0] * h[0] + h[1] * h[1] + h[2] * h[2];
|
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 }
|
||||||
|
|
||||||
EX namespace nisot {
|
EX namespace nisot {
|
||||||
|
|
|
@ -248,7 +248,7 @@ shared_ptr<glhr::GLprogram> write_shader(flagtype shader_flags) {
|
||||||
shader_flags |= SF_PERS3 | SF_DIRECT;
|
shader_flags |= SF_PERS3 | SF_DIRECT;
|
||||||
if(hyperbolic)
|
if(hyperbolic)
|
||||||
distfun = "acosh(t[3])", treset = true;
|
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;
|
distfun = "length(t.xyz)", treset = true;
|
||||||
else {
|
else {
|
||||||
if(spherephase & 4) coordinator += "t = -t;\n";
|
if(spherephase & 4) coordinator += "t = -t;\n";
|
||||||
|
|
Loading…
Reference in New Issue