mirror of
https://github.com/zenorogue/hyperrogue.git
synced 2024-11-23 21:07:17 +00:00
Panini projection
This commit is contained in:
parent
2cc06e39ba
commit
6513b3a87e
45
config.cpp
45
config.cpp
@ -713,6 +713,8 @@ EX void initConfig() {
|
||||
addsaver(camera_speed, "camera-speed", 1);
|
||||
addsaver(camera_rot_speed, "camera-rot-speed", 1);
|
||||
|
||||
addsaver(panini_alpha, "panini_alpha", 0);
|
||||
|
||||
callhooks(hooks_configfile);
|
||||
|
||||
#if CAP_CONFIG
|
||||
@ -1551,17 +1553,48 @@ EX void explain_detail() {
|
||||
));
|
||||
}
|
||||
|
||||
EX void add_edit_fov(char key IS('f')) {
|
||||
dialog::addSelItem(XLAT("field of view"), fts(vid.fov) + "°", key);
|
||||
dialog::add_action([] {
|
||||
dialog::editNumber(vid.fov, 1, 170, 1, 45, "field of view",
|
||||
EX ld max_fov_angle() {
|
||||
return acos(-panini_alpha) * 2 / degree;
|
||||
}
|
||||
|
||||
EX void add_edit_fov(char key IS('f'), bool pop IS(false)) {
|
||||
|
||||
string sfov = fts(vid.fov) + "°";
|
||||
if(panini_alpha) {
|
||||
sfov += " / " + fts(max_fov_angle()) + "°";
|
||||
}
|
||||
dialog::addSelItem(XLAT("field of view"), sfov, key);
|
||||
dialog::add_action([=] {
|
||||
if(pop) popScreen();
|
||||
dialog::editNumber(vid.fov, 1, max_fov_angle(), 1, 45, "field of view",
|
||||
XLAT(
|
||||
"Horizontal field of view, in angles. "
|
||||
"This affects the Hypersian Rug mode (even when stereo is OFF) "
|
||||
"and non-disk models.")
|
||||
"and non-disk models.") + "\n\n" +
|
||||
XLAT(
|
||||
"Must be less than %1°. Panini projection can be used to get higher values.",
|
||||
fts(max_fov_angle())
|
||||
)
|
||||
);
|
||||
dialog::bound_low(1e-8);
|
||||
dialog::bound_up(179);
|
||||
dialog::bound_up(max_fov_angle() - 0.01);
|
||||
dialog::extra_options = [] {
|
||||
dialog::addSelItem(XLAT("Panini projection"), fts(panini_alpha), 'P');
|
||||
dialog::add_action([] {
|
||||
popScreen();
|
||||
dialog::editNumber(panini_alpha, 0, 1, 0.1, 0, "Panini parameter",
|
||||
XLAT(
|
||||
"The Panini projection is an alternative perspective projection "
|
||||
"which allows very wide field-of-view values. HyperRogue uses "
|
||||
"a quick implementation, so parameter values too close to 1 may "
|
||||
"be buggy; try e.g. 0.9 instead.")
|
||||
);
|
||||
dialog::reaction = ray::reset_raycaster;
|
||||
dialog::extra_options = [] {
|
||||
add_edit_fov('F', true);
|
||||
};
|
||||
});
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
|
2
glhr.cpp
2
glhr.cpp
@ -154,7 +154,7 @@ void display(const glmatrix& m) {
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
glmatrix operator * (glmatrix m1, glmatrix m2) {
|
||||
EX glmatrix operator * (glmatrix m1, glmatrix m2) {
|
||||
glmatrix res;
|
||||
for(int i=0; i<4; i++)
|
||||
for(int j=0; j<4; j++) {
|
||||
|
@ -22,6 +22,8 @@ EX bool spatial_graphics;
|
||||
EX bool wmspatial, wmescher, wmplain, wmblack, wmascii, wmascii3;
|
||||
EX bool mmspatial, mmhigh, mmmon, mmitem;
|
||||
|
||||
EX ld panini_alpha = 0;
|
||||
|
||||
EX int detaillevel = 0;
|
||||
|
||||
EX bool first_cell_to_draw = true;
|
||||
@ -4878,7 +4880,8 @@ EX void calcparam() {
|
||||
cd->xcenter += cd->scrsize * pconf.xposition;
|
||||
cd->ycenter += cd->scrsize * pconf.yposition;
|
||||
|
||||
cd->tanfov = tan(vid.fov * degree / 2);
|
||||
ld fov = vid.fov * degree / 2;
|
||||
cd->tanfov = sin(fov) / (cos(fov) + panini_alpha);
|
||||
|
||||
callhooks(hooks_calcparam);
|
||||
reset_projection();
|
||||
|
@ -208,6 +208,7 @@ EX namespace models {
|
||||
EX bool has_orientation(eModel m) {
|
||||
if(m == mdHorocyclic)
|
||||
return hyperbolic;
|
||||
if((m == mdPerspective || m == mdGeodesic) && panini_alpha) return true;
|
||||
return
|
||||
among(m, mdHalfplane, mdPolynomial, mdPolygonal, mdTwoPoint, mdJoukowsky, mdJoukowskyInverted, mdSpiral, mdSimulatedPerspective, mdTwoHybrid, mdHorocyclic, mdAxial, mdAntiAxial, mdQuadrant,
|
||||
mdWerner, mdAitoff, mdHammer, mdLoximuthal, mdWinkelTripel) || mdBandAny();
|
||||
@ -868,6 +869,10 @@ EX namespace models {
|
||||
PHASEFROM(2);
|
||||
shift_arg_formula(vpconf.skiprope);
|
||||
}
|
||||
else if(argis("-palpha")) {
|
||||
PHASEFROM(2);
|
||||
shift_arg_formula(panini_alpha, reset_all_shaders);
|
||||
}
|
||||
else if(argis("-zoom")) {
|
||||
PHASEFROM(2); shift_arg_formula(vpconf.scale);
|
||||
}
|
||||
|
@ -370,14 +370,34 @@ void enable_raycaster() {
|
||||
" mediump mat4 vw = uStart * xzspin(-lambda) * xpush(eye) * yzspin(phi);\n"
|
||||
" mediump vec4 at0 = vec4(0., 0., 1., 0.);\n";
|
||||
|
||||
else fmain +=
|
||||
" mediump mat4 vw = uStart;\n"
|
||||
" mediump vec4 at0 = at;\n"
|
||||
" gl_FragColor = vec4(0,0,0,1);\n"
|
||||
" mediump float left = 1.;\n"
|
||||
" at0.y = -at.y;\n"
|
||||
" at0.w = 0.;\n"
|
||||
" at0.xyz = at0.xyz / length(at0.xyz);\n";
|
||||
else {
|
||||
fmain +=
|
||||
" mediump mat4 vw = uStart;\n"
|
||||
" mediump vec4 at0 = at;\n"
|
||||
" gl_FragColor = vec4(0,0,0,1);\n"
|
||||
" mediump float left = 1.;\n"
|
||||
" at0.y = -at.y;\n"
|
||||
" at0.w = 0.;\n";
|
||||
|
||||
if(panini_alpha) fmain +=
|
||||
"mediump float hr = at0.x*at0.x;\n"
|
||||
"mediump float alpha = " + to_glsl(panini_alpha) + ";\n"
|
||||
"mediump float A = 1. + hr;\n"
|
||||
"mediump float B = -2.*hr*alpha;\n"
|
||||
"mediump float C = 1. - hr*alpha*alpha;\n"
|
||||
"B /= A; C /= A;\n"
|
||||
|
||||
"mediump float hz = B / 2. + sqrt(C + B*B/4.);\n"
|
||||
"if(abs(hz) > 1e-3) {"
|
||||
"at0.xyz *= hz+alpha;\n"
|
||||
"at0.z = hz;\n}"
|
||||
" else at0.z = 0.;\n"
|
||||
"\n"
|
||||
;
|
||||
|
||||
fmain +=
|
||||
" at0.xyz = at0.xyz / length(at0.xyz);\n";
|
||||
}
|
||||
|
||||
if(hyperbolic) fsh += " mediump float len(mediump vec4 x) { return x[3]; }\n";
|
||||
else if(sphere && rotspace) fsh += " mediump float len(mediump vec4 x) { return 1.+x.x*x.x+x.y*x.y-x.z*x.z-x.w*x.w; }\n";
|
||||
@ -1091,6 +1111,7 @@ void enable_raycaster() {
|
||||
}
|
||||
|
||||
#ifndef GLES_ONLY
|
||||
/* todo: fix for Panini */
|
||||
fmain +=
|
||||
" gl_FragDepth = (" + to_glsl(-vnear-vfar)+"+w*" + to_glsl(2*vnear*vfar)+"/z)/" + to_glsl(vnear-vfar)+";\n"
|
||||
" gl_FragDepth = (gl_FragDepth + 1.) / 2.;\n";
|
||||
|
27
shaders.cpp
27
shaders.cpp
@ -60,6 +60,12 @@ glhr::glmatrix model_orientation_gl() {
|
||||
return s;
|
||||
}
|
||||
|
||||
EX void reset_all_shaders() {
|
||||
ray::reset_raycaster();
|
||||
compiled_programs.clear();
|
||||
matched_programs.clear();
|
||||
}
|
||||
|
||||
shared_ptr<glhr::GLprogram> write_shader(flagtype shader_flags) {
|
||||
string varying, vsh, fsh, vmain = "void main() {\n", fmain = "void main() {\n";
|
||||
|
||||
@ -332,6 +338,21 @@ shared_ptr<glhr::GLprogram> write_shader(flagtype shader_flags) {
|
||||
}
|
||||
if(shader_flags & GF_LEVELS) vmain += "vPos = t;\n";
|
||||
if(treset) vmain += "t[3] = 1.0;\n";
|
||||
|
||||
if(WDIM == 3 && panini_alpha) {
|
||||
vmain += "t = uPP * t;", vsh += "uniform mediump mat4 uPP;";
|
||||
/* panini */
|
||||
vmain += "t.w += 1.; t *= 2. / t.w; t.w -= 1.;\n";
|
||||
vmain += "float s = t.z;";
|
||||
vmain += "float l = length(t.xyz);";
|
||||
vmain += "t /= max(length(t.xz), 1e-2);\n";
|
||||
vmain += "t.z += " + glhr::to_glsl(panini_alpha) + ";\n";
|
||||
vmain += "t *= l;\n";
|
||||
vmain += "t.w = 1.;\n";
|
||||
frustum_culling = false;
|
||||
shader_flags |= SF_ORIENT;
|
||||
}
|
||||
|
||||
vmain += "gl_Position = uP * t;\n";
|
||||
}
|
||||
|
||||
@ -485,7 +506,8 @@ void display_data::set_projection(int ed, ld shift) {
|
||||
for(int i=0; i<3; i++) NLP[3][i] = NLP[i][3] = 0;
|
||||
NLP[3][3] = 1;
|
||||
}
|
||||
glhr::projection_multiply(glhr::tmtogl_transpose(NLP));
|
||||
if(!(shader_flags & SF_ORIENT))
|
||||
glhr::projection_multiply(glhr::tmtogl_transpose(NLP));
|
||||
}
|
||||
if(ed) {
|
||||
glhr::using_eyeshift = true;
|
||||
@ -520,6 +542,9 @@ void display_data::set_projection(int ed, ld shift) {
|
||||
if(get_shader_flags() & SF_USE_ALPHA)
|
||||
pp[3][2] = GLfloat(pconf.alpha);
|
||||
|
||||
if(nisot::local_perspective_used())
|
||||
pp = glhr::tmtogl_transpose(NLP) * pp;
|
||||
|
||||
if(get_shader_flags() & SF_ORIENT) {
|
||||
if(GDIM == 3) for(int a=0; a<4; a++)
|
||||
models::apply_orientation_yz(pp[a][1], pp[a][2]);
|
||||
|
Loading…
Reference in New Issue
Block a user