1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2024-12-25 17:40:36 +00:00

improved the quality of 3D models from conformal menu

This commit is contained in:
Zeno Rogue 2018-03-24 15:15:30 +01:00
parent 74cc23f1c2
commit d3c9bfdd92
10 changed files with 72 additions and 27 deletions

View File

@ -263,6 +263,10 @@ void stereo::set_viewport(int ed) {
glViewport(vid.xres/2, 0, vid.xres/2, vid.yres); glViewport(vid.xres/2, 0, vid.xres/2, vid.yres);
} }
bool model_needs_depth() {
return pmodel == mdBall || pmodel == mdHyperboloid || pmodel == mdHemisphere;
}
void setGLProjection(int col) { void setGLProjection(int col) {
DEBB(DF_GRAPH, (debugfile,"setGLProjection\n")); DEBB(DF_GRAPH, (debugfile,"setGLProjection\n"));
GLERR("pre_setGLProjection"); GLERR("pre_setGLProjection");
@ -299,17 +303,17 @@ void setGLProjection(int col) {
//glLineWidth(1.0f); //glLineWidth(1.0f);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
if(pmodel == mdBall || pmodel == mdHyperboloid || pmodel == mdHemisphere) { if(model_needs_depth()) {
#ifdef GL_ES #ifdef GL_ES
glClearDepthf(1.0f); glClearDepthf(1.0f);
#else #else
glClearDepth(1.0f); glClearDepth(1.0f);
#endif #endif
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL); glDepthFunc(GL_LEQUAL);
glhr::set_depthtest(true);
} }
else else
glDisable(GL_DEPTH_TEST); glhr::set_depthtest(false);
GLERR("setGLProjection"); GLERR("setGLProjection");
@ -524,6 +528,8 @@ bool gl_print(int x, int y, int shift, int size, const char *s, int color, int a
bool clicked = (mousex >= x && mousey <= y && mousex <= x+tsize && mousey >= y-ysiz); bool clicked = (mousex >= x && mousey <= y && mousex <= x+tsize && mousey >= y-ysiz);
glhr::set_depthtest(false);
for(int i=0; s[i];) { for(int i=0; s[i];) {
int tabid = getnext(s,i); int tabid = getnext(s,i);
@ -917,6 +923,7 @@ void drawCircle(int x, int y, int size, int color) {
glcoords.push_back(make_array<GLfloat>(x + size * sin(rr), y + size * cos(rr), stereo::scrdist)); glcoords.push_back(make_array<GLfloat>(x + size * sin(rr), y + size * cos(rr), stereo::scrdist));
} }
glhr::vertices(glcoords); glhr::vertices(glcoords);
glhr::set_depthtest(false);
glDrawArrays(GL_LINE_LOOP, 0, pts); glDrawArrays(GL_LINE_LOOP, 0, pts);
return; return;
} }

View File

@ -337,6 +337,7 @@ void initConfig() {
addsaver(stereo::anaglyph_eyewidth, "eyewidth-anaglyph", 0.1); addsaver(stereo::anaglyph_eyewidth, "eyewidth-anaglyph", 0.1);
addsaver(stereo::fov, "field-of-vision", 90); addsaver(stereo::fov, "field-of-vision", 90);
addsaverenum(stereo::mode, "stereo-mode"); addsaverenum(stereo::mode, "stereo-mode");
addsaver(vid.euclid_to_sphere, "euclid to sphere projection", 1.5);
#if CAP_SHMUP #if CAP_SHMUP
shmup::initConfig(); shmup::initConfig();
@ -1130,6 +1131,17 @@ void showStereo() {
}; };
} }
void config_camera_rotation() {
dialog::editNumber(vid.ballangle, 0, 90, 5, 0, XLAT("camera rotation in 3D models"),
"Rotate the camera in 3D models (ball model, hyperboloid, and hemisphere). "
"Note that hyperboloid and hemisphere models are also available in the "
"Hypersian Rug surfaces menu, but they are rendered differently there -- "
"they are rendered by making a flat picture first, then mapping it to a surface. "
"This makes the output better in some ways, but 3D effects are lost. "
"Hypersian Rug model also allows more camera freedom."
);
}
void show3D() { void show3D() {
cmode = sm::SIDE | sm::A3 | sm::MAYDARK; cmode = sm::SIDE | sm::A3 | sm::MAYDARK;
gamescreen(0); gamescreen(0);
@ -1158,7 +1170,7 @@ void show3D() {
dialog::addBreak(50); dialog::addBreak(50);
dialog::addBoolItem(XLAT("ball model"), pmodel == mdBall, 'B'); dialog::addBoolItem(XLAT("ball model"), pmodel == mdBall, 'B');
dialog::addBoolItem(XLAT("hyperboloid model"), pmodel == mdHyperboloid, 'M'); dialog::addBoolItem(XLAT("hyperboloid model"), pmodel == mdHyperboloid, 'M');
dialog::addSelItem(XLAT("camera rotation in ball model"), fts3(vid.ballangle), 'b'); dialog::addSelItem(XLAT("camera rotation in 3D models"), fts3(vid.ballangle), 'b');
dialog::addSelItem(XLAT("projection in ball model"), fts3(vid.ballproj), 'x'); dialog::addSelItem(XLAT("projection in ball model"), fts3(vid.ballproj), 'x');
if(sphere) if(sphere)
@ -1181,10 +1193,8 @@ void show3D() {
dialog::handleNavigation(sym, uni); dialog::handleNavigation(sym, uni);
if(uni == 'n') if(uni == 'n')
cmode &= sm::A3,
dialog::editNumber(geom3::highdetail, 0, 5, .5, 7, XLAT("High detail range"), ""); dialog::editNumber(geom3::highdetail, 0, 5, .5, 7, XLAT("High detail range"), "");
else if(uni == 'm') else if(uni == 'm')
cmode &= sm::A3,
dialog::editNumber(geom3::middetail, 0, 5, .5, 7, XLAT("Mid detail range"), ""); dialog::editNumber(geom3::middetail, 0, 5, .5, 7, XLAT("Mid detail range"), "");
else if(uni == 'c') else if(uni == 'c')
tc_camera = ticks, tc_camera = ticks,
@ -1209,22 +1219,17 @@ void show3D() {
pushScreen(showStereo); pushScreen(showStereo);
else if(uni == 'y') else if(uni == 'y')
cmode &= sm::A3,
dialog::editNumber(vid.yshift, 0, 1, .1, 0, XLAT("Y shift"), dialog::editNumber(vid.yshift, 0, 1, .1, 0, XLAT("Y shift"),
"Don't center on the player character." "Don't center on the player character."
); );
else if(uni == 's') else if(uni == 's')
cmode &= sm::A3,
dialog::editNumber(vid.camera_angle, -180, 180, 5, 0, XLAT("camera rotation"), dialog::editNumber(vid.camera_angle, -180, 180, 5, 0, XLAT("camera rotation"),
"Rotate the camera. Can be used to obtain a first person perspective, " "Rotate the camera. Can be used to obtain a first person perspective, "
"or third person perspective when combined with Y shift." "or third person perspective when combined with Y shift."
); );
else if(uni == 'b') else if(uni == 'b')
cmode &= sm::A3, config_camera_rotation();
dialog::editNumber(vid.ballangle, 0, 90, 5, 0, XLAT("camera rotation in ball model"),
"Rotate the camera in ball/hyperboloid model.");
else if(uni == 'x') else if(uni == 'x')
cmode &= sm::A3,
dialog::editNumber(vid.ballproj, 0, 100, .1, 0, XLAT("projection in ball model"), dialog::editNumber(vid.ballproj, 0, 100, .1, 0, XLAT("projection in ball model"),
"This parameter affects the ball model the same way as the projection parameter affects the disk model."); "This parameter affects the ball model the same way as the projection parameter affects the disk model.");
else if(uni == 'i') else if(uni == 'i')

View File

@ -537,6 +537,7 @@ namespace conformal {
{ "right", "up", "left", "down" }, { "right", "up", "left", "down" },
{ "right", "up", "left", "down" }, { "right", "up", "left", "down" },
{ "right", "up", "left", "down" }, { "right", "up", "left", "down" },
{ "right", "up", "left", "down" },
{ "right", "up", "left", "down" } { "right", "up", "left", "down" }
}; };
@ -577,7 +578,7 @@ namespace conformal {
dialog::addBoolItem("Switch", false, '6'); dialog::addBoolItem("Switch", false, '6');
} }
if(pmodel == 4) { if(pmodel == mdPolynomial) {
dialog::addSelItem(XLAT("coefficient"), dialog::addSelItem(XLAT("coefficient"),
fts4(polygonal::coefr[polygonal::coefid]), 'x'); fts4(polygonal::coefr[polygonal::coefid]), 'x');
dialog::addSelItem(XLAT("coefficient (imaginary)"), dialog::addSelItem(XLAT("coefficient (imaginary)"),
@ -585,12 +586,20 @@ namespace conformal {
dialog::addSelItem(XLAT("which coefficient"), its(polygonal::coefid), 'n'); dialog::addSelItem(XLAT("which coefficient"), its(polygonal::coefid), 'n');
} }
if(pmodel == 3) { if(pmodel == mdPolygonal) {
dialog::addSelItem(XLAT("polygon sides"), its(polygonal::SI), 'x'); dialog::addSelItem(XLAT("polygon sides"), its(polygonal::SI), 'x');
dialog::addSelItem(XLAT("star factor"), fts(polygonal::STAR), 'y'); dialog::addSelItem(XLAT("star factor"), fts(polygonal::STAR), 'y');
dialog::addSelItem(XLAT("degree of the approximation"), its(polygonal::deg), 'n'); dialog::addSelItem(XLAT("degree of the approximation"), its(polygonal::deg), 'n');
} }
if(pmodel == mdBall || pmodel == mdHyperboloid || pmodel == mdHemisphere) {
dialog::addSelItem(XLAT("camera rotation in 3D models"), fts3(vid.ballangle), 'b');
}
if(pmodel == mdHemisphere) {
dialog::addSelItem(XLAT("euclid to sphere projection"), fts3(vid.euclid_to_sphere), 'l');
}
if(!bounded && !euclid) dialog::addBoolItem(XLAT("prepare the line animation"), (on), 'e'); if(!bounded && !euclid) dialog::addBoolItem(XLAT("prepare the line animation"), (on), 'e');
if(on) dialog::addSelItem(XLAT("animation speed"), fts(lvspeed), 'a'); if(on) dialog::addSelItem(XLAT("animation speed"), fts(lvspeed), 'a');
@ -633,6 +642,14 @@ namespace conformal {
create(); create();
} }
} }
else if(uni == 'b')
config_camera_rotation();
else if(uni == 'l') {
dialog::editNumber(vid.euclid_to_sphere, 0, 10, .1, 1, XLAT("euclid to sphere projection"),
"Stereographic projection to a sphere. Choose the radius of the sphere."
);
dialog::scaleLog();
}
else if(uni == 'o') else if(uni == 'o')
autoband = !autoband; autoband = !autoband;
else if(uni == 'm' || uni == 'M') { else if(uni == 'm' || uni == 'M') {

View File

@ -829,7 +829,7 @@ namespace dialog {
ne.intval = NULL; ne.intval = NULL;
ne.positive = false; ne.positive = false;
dialogflags = (cmode & sm::A3); dialogflags = (cmode & sm::A3);
if(cmode & sm::SIDE) dialogflags |= sm::MAYDARK; if(cmode & sm::SIDE) dialogflags |= sm::MAYDARK | sm::SIDE;
cmode |= sm::NUMBER; cmode |= sm::NUMBER;
pushScreen(drawNumberDialog); pushScreen(drawNumberDialog);
reaction = reaction_t(); reaction = reaction_t();

View File

@ -2309,6 +2309,7 @@ void drawaura() {
glhr::switch_mode(glhr::gmVarColored); glhr::switch_mode(glhr::gmVarColored);
glhr::id_modelview(); glhr::id_modelview();
glhr::prepare(auravertices); glhr::prepare(auravertices);
glhr::set_depthtest(false);
glDrawArrays(GL_TRIANGLES, 0, size(auravertices)); glDrawArrays(GL_TRIANGLES, 0, size(auravertices));

View File

@ -647,7 +647,7 @@ extern reaction_t help_delegate;
struct videopar { struct videopar {
ld scale, alpha, sspeed, mspeed, yshift, camera_angle; ld scale, alpha, sspeed, mspeed, yshift, camera_angle;
ld ballangle, ballproj; ld ballangle, ballproj, euclid_to_sphere;
int mobilecompasssize; int mobilecompasssize;
int aurastr, aurasmoothen; int aurastr, aurasmoothen;

View File

@ -129,20 +129,23 @@ void applymodel(hyperpoint H, hyperpoint& ret) {
switch(cgclass) { switch(cgclass) {
case gcHyperbolic: { case gcHyperbolic: {
ld zl = zlevel(H);
ret = H / H[2]; ret = H / H[2];
ret[2] = sqrt(1 - sqhypot2(ret)); ret[2] = sqrt(1 - sqhypot2(ret));
ret = ret * (1 + (zl - 1) * ret[2]);
break; break;
} }
case gcEuclid: { case gcEuclid: {
// stereographic projection to a sphere // stereographic projection to a sphere
auto hd = hdist0(H) / H[2]; auto hd = hdist0(H) / vid.euclid_to_sphere;
if(hd == 0) H[2] = -1; if(hd == 0) ret = hpxyz(0, 0, -1);
else { else {
ld x = 2 * hd / (1 + hd * hd); ld x = 2 * hd / (1 + hd * hd);
ld y = x / hd; ld y = x / hd;
H = H * x / (hd * H[2]); ret = H * x / hd / vid.euclid_to_sphere;
H[2] = 1 - y; ret[2] = (1 - y);
ret = ret * (1 + (H[2]-1) * y / vid.euclid_to_sphere);
} }
break; break;
} }
@ -153,7 +156,7 @@ void applymodel(hyperpoint H, hyperpoint& ret) {
} }
} }
ret = rotmatrix(0, 2, ball) * ret; ret = rotmatrix(M_PI/2 + ball, 1, 2) * ret;
ghcheck(ret, H); ghcheck(ret, H);
return; return;

View File

@ -250,7 +250,7 @@ void setmatrix(int useV, const transmatrix& V) {
GLfloat mat[16] = { GLfloat mat[16] = {
1, 0, 0, 0, 1, 0, 0, 0,
0, 1, 0, 0, 0, 1, 0, 0,
0, 0, 0, 0, 0, 0, -1, 0,
0, 0, stereo::scrdist, 1 0, 0, stereo::scrdist, 1
}; };
glhr::set_modelview(glhr::as_glmatrix(mat)); glhr::set_modelview(glhr::as_glmatrix(mat));
@ -299,14 +299,17 @@ void gldraw(int useV, const transmatrix& V, const vector<glvertex>& v, int ps, i
glEnable(GL_STENCIL_TEST); glEnable(GL_STENCIL_TEST);
glColorMask( GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE ); glColorMask( GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE );
glhr::set_depthtest(false);
glStencilOp( GL_INVERT, GL_INVERT, GL_INVERT); glStencilOp( GL_INVERT, GL_INVERT, GL_INVERT);
glStencilFunc( GL_ALWAYS, 0x1, 0x1 ); glStencilFunc( GL_ALWAYS, 0x1, 0x1 );
glhr::color2(0xFFFFFFFF); glhr::color2(0xFFFFFFFF);
glDrawArrays(tinf ? GL_TRIANGLES : GL_TRIANGLE_FAN, ps, pq); glDrawArrays(tinf ? GL_TRIANGLES : GL_TRIANGLE_FAN, ps, pq);
if(flags & POLY_INVERSE) {
stereo::set_mask(ed); stereo::set_mask(ed);
glhr::color2(col); glhr::color2(col);
glhr::set_depthtest(model_needs_depth());
if(flags & POLY_INVERSE) {
glStencilOp( GL_ZERO, GL_ZERO, GL_ZERO); glStencilOp( GL_ZERO, GL_ZERO, GL_ZERO);
glStencilFunc( GL_NOTEQUAL, 1, 1); glStencilFunc( GL_NOTEQUAL, 1, 1);
GLfloat xx = vid.xres; GLfloat xx = vid.xres;
@ -324,8 +327,6 @@ void gldraw(int useV, const transmatrix& V, const vector<glvertex>& v, int ps, i
setmatrix(useV, V); setmatrix(useV, V);
} }
else { else {
stereo::set_mask(ed);
glhr::color2(col);
glStencilOp( GL_ZERO, GL_ZERO, GL_ZERO); glStencilOp( GL_ZERO, GL_ZERO, GL_ZERO);
glStencilFunc( GL_EQUAL, 1, 1); glStencilFunc( GL_EQUAL, 1, 1);
glDrawArrays(tinf ? GL_TRIANGLES : GL_TRIANGLE_FAN, ps, pq); glDrawArrays(tinf ? GL_TRIANGLES : GL_TRIANGLE_FAN, ps, pq);
@ -337,6 +338,7 @@ void gldraw(int useV, const transmatrix& V, const vector<glvertex>& v, int ps, i
if(outline) { if(outline) {
glhr::color2(outline); glhr::color2(outline);
glhr::set_depthtest(model_needs_depth());
glDrawArrays(GL_LINE_STRIP, ps, pq); glDrawArrays(GL_LINE_STRIP, ps, pq);
} }
} }

View File

@ -670,4 +670,13 @@ void store_in_buffer(vector<glvertex>& v) {
#endif #endif
} }
bool current_depthtest;
void set_depthtest(bool b) {
if(b != current_depthtest) {
current_depthtest = b;
if(b) glEnable(GL_DEPTH_TEST);
else glDisable(GL_DEPTH_TEST);
}
}
} }

View File

@ -483,6 +483,7 @@ void texture_config::drawRawTexture() {
} }
glhr::set_modelview(glhr::translate(0, 0, stereo::scrdist)); glhr::set_modelview(glhr::translate(0, 0, stereo::scrdist));
glhr::prepare(rtver); glhr::prepare(rtver);
glhr::set_depthtest(false);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4); glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
} }