1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2024-12-24 17:10: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);
}
bool model_needs_depth() {
return pmodel == mdBall || pmodel == mdHyperboloid || pmodel == mdHemisphere;
}
void setGLProjection(int col) {
DEBB(DF_GRAPH, (debugfile,"setGLProjection\n"));
GLERR("pre_setGLProjection");
@ -299,17 +303,17 @@ void setGLProjection(int col) {
//glLineWidth(1.0f);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
if(pmodel == mdBall || pmodel == mdHyperboloid || pmodel == mdHemisphere) {
if(model_needs_depth()) {
#ifdef GL_ES
glClearDepthf(1.0f);
#else
glClearDepth(1.0f);
#endif
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glhr::set_depthtest(true);
}
else
glDisable(GL_DEPTH_TEST);
glhr::set_depthtest(false);
GLERR("setGLProjection");
@ -523,6 +527,8 @@ bool gl_print(int x, int y, int shift, int size, const char *s, int color, int a
int ysiz = f.heights[32] * size / gsiz;
bool clicked = (mousex >= x && mousey <= y && mousex <= x+tsize && mousey >= y-ysiz);
glhr::set_depthtest(false);
for(int i=0; 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));
}
glhr::vertices(glcoords);
glhr::set_depthtest(false);
glDrawArrays(GL_LINE_LOOP, 0, pts);
return;
}

View File

@ -337,6 +337,7 @@ void initConfig() {
addsaver(stereo::anaglyph_eyewidth, "eyewidth-anaglyph", 0.1);
addsaver(stereo::fov, "field-of-vision", 90);
addsaverenum(stereo::mode, "stereo-mode");
addsaver(vid.euclid_to_sphere, "euclid to sphere projection", 1.5);
#if CAP_SHMUP
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() {
cmode = sm::SIDE | sm::A3 | sm::MAYDARK;
gamescreen(0);
@ -1158,7 +1170,7 @@ void show3D() {
dialog::addBreak(50);
dialog::addBoolItem(XLAT("ball model"), pmodel == mdBall, 'B');
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');
if(sphere)
@ -1181,10 +1193,8 @@ void show3D() {
dialog::handleNavigation(sym, uni);
if(uni == 'n')
cmode &= sm::A3,
dialog::editNumber(geom3::highdetail, 0, 5, .5, 7, XLAT("High detail range"), "");
else if(uni == 'm')
cmode &= sm::A3,
dialog::editNumber(geom3::middetail, 0, 5, .5, 7, XLAT("Mid detail range"), "");
else if(uni == 'c')
tc_camera = ticks,
@ -1209,22 +1219,17 @@ void show3D() {
pushScreen(showStereo);
else if(uni == 'y')
cmode &= sm::A3,
dialog::editNumber(vid.yshift, 0, 1, .1, 0, XLAT("Y shift"),
"Don't center on the player character."
);
else if(uni == 's')
cmode &= sm::A3,
dialog::editNumber(vid.camera_angle, -180, 180, 5, 0, XLAT("camera rotation"),
"Rotate the camera. Can be used to obtain a first person perspective, "
"or third person perspective when combined with Y shift."
);
else if(uni == 'b')
cmode &= sm::A3,
dialog::editNumber(vid.ballangle, 0, 90, 5, 0, XLAT("camera rotation in ball model"),
"Rotate the camera in ball/hyperboloid model.");
config_camera_rotation();
else if(uni == 'x')
cmode &= sm::A3,
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.");
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" }
};
@ -577,7 +578,7 @@ namespace conformal {
dialog::addBoolItem("Switch", false, '6');
}
if(pmodel == 4) {
if(pmodel == mdPolynomial) {
dialog::addSelItem(XLAT("coefficient"),
fts4(polygonal::coefr[polygonal::coefid]), 'x');
dialog::addSelItem(XLAT("coefficient (imaginary)"),
@ -585,12 +586,20 @@ namespace conformal {
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("star factor"), fts(polygonal::STAR), 'y');
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(on) dialog::addSelItem(XLAT("animation speed"), fts(lvspeed), 'a');
@ -633,6 +642,14 @@ namespace conformal {
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')
autoband = !autoband;
else if(uni == 'm' || uni == 'M') {

View File

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

View File

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

View File

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

View File

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

View File

@ -250,7 +250,7 @@ void setmatrix(int useV, const transmatrix& V) {
GLfloat mat[16] = {
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 0, 0,
0, 0, -1, 0,
0, 0, stereo::scrdist, 1
};
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);
glColorMask( GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE );
glhr::set_depthtest(false);
glStencilOp( GL_INVERT, GL_INVERT, GL_INVERT);
glStencilFunc( GL_ALWAYS, 0x1, 0x1 );
glhr::color2(0xFFFFFFFF);
glDrawArrays(tinf ? GL_TRIANGLES : GL_TRIANGLE_FAN, ps, pq);
stereo::set_mask(ed);
glhr::color2(col);
glhr::set_depthtest(model_needs_depth());
if(flags & POLY_INVERSE) {
stereo::set_mask(ed);
glhr::color2(col);
glStencilOp( GL_ZERO, GL_ZERO, GL_ZERO);
glStencilFunc( GL_NOTEQUAL, 1, 1);
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);
}
else {
stereo::set_mask(ed);
glhr::color2(col);
glStencilOp( GL_ZERO, GL_ZERO, GL_ZERO);
glStencilFunc( GL_EQUAL, 1, 1);
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) {
glhr::color2(outline);
glhr::set_depthtest(model_needs_depth());
glDrawArrays(GL_LINE_STRIP, ps, pq);
}
}

View File

@ -670,4 +670,13 @@ void store_in_buffer(vector<glvertex>& v) {
#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::prepare(rtver);
glhr::set_depthtest(false);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}