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

reworked 3D vision

This commit is contained in:
Zeno Rogue 2018-02-03 13:41:49 +01:00
parent 33ebed2cf3
commit b3f047ea6a
13 changed files with 451 additions and 276 deletions

View File

@ -10,6 +10,29 @@ int utfsize(char c) {
return 4; return 4;
} }
namespace stereo {
eStereo mode;
ld ipd;
ld lr_eyewidth, anaglyph_eyewidth;
ld fov, tanfov;
GLfloat scrdist, scrdist_text;
}
bool stereo::in_anaglyph() { return stereo::mode == stereo::sAnaglyph; }
bool stereo::active() { return stereo::mode != sOFF; }
ld stereo::eyewidth() {
switch(stereo::mode) {
case stereo::sAnaglyph:
return stereo::anaglyph_eyewidth;
case stereo::sLR:
return stereo::lr_eyewidth;
default:
return 0;
}
}
bool eqs(const char* x, const char* y) { bool eqs(const char* x, const char* y) {
return *y? *x==*y?eqs(x+1,y+1):false:true; return *y? *x==*y?eqs(x+1,y+1):false:true;
} }
@ -152,36 +175,70 @@ void setcameraangle(bool b) {
} }
} }
void selectEyeGL(int ed) { void start_projection(int ed) {
DEBB(DF_GRAPH, (debugfile,"selectEyeGL\n"));
glMatrixMode(GL_PROJECTION); glMatrixMode(GL_PROJECTION);
glLoadIdentity(); glLoadIdentity();
glTranslatef((vid.xcenter*2.)/vid.xres - 1, 1 - (vid.ycenter*2.)/vid.yres, 0); glTranslatef((vid.xcenter*2.)/vid.xres - 1, 1 - (vid.ycenter*2.)/vid.yres, 0);
if(pmodel) { if(ed) {
vid.scrdist = 4 * vid.radius; if(stereo::mode == stereo::sLR) {
glTranslatef(ed * (stereo::eyewidth() - .5) * 4, 0, 0);
glScalef(2, 1, 1);
}
else {
glTranslatef(-ed * stereo::eyewidth(), 0, 0);
}
}
}
void stereo::set_projection(int ed) {
DEBB(DF_GRAPH, (debugfile,"stereo::set_projection\n"));
start_projection(ed);
if(pmodel && !stereo::active()) {
// simulate glOrtho // simulate glOrtho
GLfloat ortho[16] = { GLfloat ortho[16] = {
GLfloat(2. / vid.xres), 0, 0, 0, GLfloat(2. / vid.xres), 0, 0, 0,
0, GLfloat(-2. / vid.yres), 0, 0, 0, GLfloat(-2. / vid.yres), 0, 0,
0, 0, GLfloat(.4 / vid.scrdist), 0, 0, 0, GLfloat(.4 / stereo::scrdist), 0,
0, 0, 0, 1}; 0, 0, 0, 1};
vid.scrdist = -vid.scrdist;
glMultMatrixf(ortho); glMultMatrixf(ortho);
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
glLoadIdentity(); glLoadIdentity();
} }
else { else if(pmodel) {
float ve = ed*vid.eye;
ve *= 2; // vid.xres; ve /= vid.radius;
if(ve)
glTranslatef(-(ve * vid.radius) * (vid.alpha - (vid.radius*1./vid.xres) * vid.eye) / vid.xres, 0, 0);
float lowdepth = .1, hidepth = 1e9;
ld right = vid.xres/2 * lowdepth / stereo::scrdist;
ld left = -right;
ld top = -vid.yres/2 * lowdepth / stereo::scrdist;
ld bottom = -top;
GLfloat frustum[16] = {
GLfloat(2 * lowdepth / (right-left)), 0, 0, 0,
0, GLfloat(2 * lowdepth / (top-bottom)), 0, 0,
0, 0, -(hidepth+lowdepth)/(hidepth-lowdepth), -1,
0, 0, -2*lowdepth*hidepth/(hidepth-lowdepth), 0};
glMultMatrixf(frustum);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
if(ed) glTranslatef(stereo::ipd * vid.radius * ed/2, 0, 0);
glScalef(1, 1, -1);
glTranslatef(0, 0, stereo::scrdist);
stereo::scrdist_text = 0;
}
else {
float lowdepth = .1; float lowdepth = .1;
float hidepth = 1e9; float hidepth = 1e9;
@ -196,20 +253,22 @@ void selectEyeGL(int ed) {
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
glLoadIdentity(); glLoadIdentity();
GLfloat sc = vid.radius / (vid.yres/2.); GLfloat sc = vid.radius / (vid.yres/2.);
GLfloat mat[16] = {sc,0,0,0, 0,-sc,0,0, 0,0,-1,0, 0,0, 0,1}; GLfloat mat[16] = {sc,0,0,0, 0,-sc,0,0, 0,0,-1,0, 0,0, 0,1};
glMultMatrixf(mat); glMultMatrixf(mat);
if(ve) glTranslatef(ve, 0, vid.eye); if(ed) glTranslatef(stereo::ipd*ed/2, 0, 0);
vid.scrdist = vid.yres * sc / 2;
stereo::scrdist_text = vid.yres * sc / 2;
} }
cameraangle_on = false; cameraangle_on = false;
} }
void selectEyeMask(int ed) { void stereo::set_mask(int ed) {
if(ed == 0) { if(ed == 0 || stereo::mode != stereo::sAnaglyph) {
glColorMask( GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE ); glColorMask( GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE );
} }
else if(ed == 1) { else if(ed == 1) {
@ -220,6 +279,15 @@ void selectEyeMask(int ed) {
} }
} }
void stereo::set_viewport(int ed) {
if(ed == 0 || stereo::mode != stereo::sLR)
glViewport(0, 0, vid.xres, vid.yres);
else if(ed == 1)
glViewport(0, 0, vid.xres/2, vid.yres);
else if(ed == -1)
glViewport(vid.xres/2, 0, vid.xres/2, vid.yres);
}
void setGLProjection(int col) { void setGLProjection(int col) {
DEBB(DF_GRAPH, (debugfile,"setGLProjection\n")); DEBB(DF_GRAPH, (debugfile,"setGLProjection\n"));
@ -261,7 +329,7 @@ void setGLProjection(int col) {
else else
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
selectEyeGL(0); stereo::set_projection(0);
} }
#if CAP_GLFONT #if CAP_GLFONT
@ -475,7 +543,7 @@ bool gl_print(int x, int y, int shift, int size, const char *s, int color, int a
displaystr(x+w, y+h, 1, 10, "X", 0xFFFFFF, 8); displaystr(x+w, y+h, 1, 10, "X", 0xFFFFFF, 8);
markcorner = true; markcorner = true;
} */ } */
for(int i=0; s[i];) { for(int i=0; s[i];) {
// glListBase(f.list_base); // glListBase(f.list_base);
@ -488,11 +556,11 @@ bool gl_print(int x, int y, int shift, int size, const char *s, int color, int a
int hi = f.heights[tabid] * size/gsiz; int hi = f.heights[tabid] * size/gsiz;
GLERR("pre-print"); GLERR("pre-print");
for(int ed = (vid.goteyes && shift)?-1:0; ed<2; ed+=2) { for(int ed = (stereo::active() && shift)?-1:0; ed<2; ed+=2) {
glPushMatrix(); glPushMatrix();
glTranslatef(x-ed*shift-vid.xcenter,y-vid.ycenter, vid.scrdist); glTranslatef(x-ed*shift-vid.xcenter,y-vid.ycenter, stereo::scrdist_text);
selectEyeMask(ed); stereo::set_mask(ed);
glBindTexture(GL_TEXTURE_2D, f.textures[tabid]); glBindTexture(GL_TEXTURE_2D, f.textures[tabid]);
#if 1 #if 1
@ -516,7 +584,7 @@ bool gl_print(int x, int y, int shift, int size, const char *s, int color, int a
glPopMatrix(); glPopMatrix();
} }
if(vid.goteyes) selectEyeMask(0); if(stereo::active() && shift) stereo::set_mask(0);
GLERR("print"); GLERR("print");
@ -782,7 +850,7 @@ ld realradius() {
ld vradius = vid.radius; ld vradius = vid.radius;
if(sphere) { if(sphere) {
if(sphereflipped()) if(sphereflipped())
vradius /= sqrt(vid.alphax*vid.alphax - 1); vradius /= sqrt(vid.alpha*vid.alpha - 1);
else else
vradius = 1e12; // use the following vradius = 1e12; // use the following
} }
@ -885,7 +953,7 @@ void drawCircle(int x, int y, int size, int color) {
float rr = (M_PI * 2 * r) / pts; float rr = (M_PI * 2 * r) / pts;
glcoords[r][0] = x + size * sin(rr); glcoords[r][0] = x + size * sin(rr);
glcoords[r][1] = y + size * cos(rr); glcoords[r][1] = y + size * cos(rr);
glcoords[r][2] = vid.scrdist; glcoords[r][2] = stereo::scrdist;
} }
qglcoords = pts; qglcoords = pts;
@ -940,7 +1008,7 @@ void displayColorButton(int x, int y, const string& name, int key, int align, in
} }
ld textscale() { ld textscale() {
return vid.fsize / (vid.radius * crossf) * (1+vid.alphax) * 2; return vid.fsize / (vid.radius * crossf) * (1+vid.alpha) * 2;
} }
// bool notgl = false; // bool notgl = false;

View File

@ -102,6 +102,9 @@ int arg::readCommon() {
else if(argis("-nofps")) { else if(argis("-nofps")) {
nofps = true; nofps = true;
} }
else if(argis("-nohud")) {
nohud = true;
}
else if(argis("-back")) { else if(argis("-back")) {
shift(); backcolor = strtol(args(), NULL, 16); shift(); backcolor = strtol(args(), NULL, 16);
} }
@ -132,6 +135,10 @@ int arg::readCommon() {
shift(); int q = argi(); shift(); int q = argi();
placeItems(q, i); placeItems(q, i);
} }
else if(argis("-SM")) {
PHASE(2);
shift(); stereo::mode = stereo::eStereo(argi());
}
else if(argis("-IU")) { else if(argis("-IU")) {
PHASE(3) cheater++; timerghost = false; PHASE(3) cheater++; timerghost = false;
shift(); eItem i = readItem(args()); shift(); eItem i = readItem(args());

View File

@ -248,7 +248,6 @@ void initConfig() {
// special graphics // special graphics
addsaver(vid.eye, "eye distance", 0);
addsaver(vid.ballangle, "ball angle", 20); addsaver(vid.ballangle, "ball angle", 20);
addsaver(vid.yshift, "Y shift", 0); addsaver(vid.yshift, "Y shift", 0);
addsaver(vid.camera_angle, "camera angle", 0); addsaver(vid.camera_angle, "camera angle", 0);
@ -332,6 +331,12 @@ void initConfig() {
addsaver(viewdists, "expansion mode"); addsaver(viewdists, "expansion mode");
addsaver(backbrightness, "brightness behind sphere"); addsaver(backbrightness, "brightness behind sphere");
addsaver(stereo::ipd, "interpupilar-distance", 0.05);
addsaver(stereo::lr_eyewidth, "eyewidth-lr", 0.5);
addsaver(stereo::anaglyph_eyewidth, "eyewidth-anaglyph", 0.1);
addsaver(stereo::fov, "field-of-vision", 90);
addsaverenum(stereo::mode, "stereo-mode");
#if CAP_SHMUP #if CAP_SHMUP
shmup::initConfig(); shmup::initConfig();
@ -437,7 +442,7 @@ void loadOldConfig(FILE *f) {
float a, b, c, d; float a, b, c, d;
err=fscanf(f, "%f%f%f%f\n", &a, &b, &c, &d); err=fscanf(f, "%f%f%f%f\n", &a, &b, &c, &d);
if(err == 4) { if(err == 4) {
vid.scale = a; vid.eye = b; vid.alpha = c; vid.sspeed = d; vid.scale = a; vid.alpha = c; vid.sspeed = d;
} }
err=fscanf(f, "%d%d%d%d%d%d%d", &vid.wallmode, &vid.monmode, &vid.axes, &musicvolume, &vid.framelimit, &gl, &vid.antialias); err=fscanf(f, "%d%d%d%d%d%d%d", &vid.wallmode, &vid.monmode, &vid.axes, &musicvolume, &vid.framelimit, &gl, &vid.antialias);
vid.usingGL = gl; vid.usingGL = gl;
@ -1047,6 +1052,66 @@ string explain3D(ld *param) {
return ""; return "";
} }
void showStereo() {
cmode = sm::SIDE | sm::A3 | sm::MAYDARK;
gamescreen(0);
using namespace geom3;
dialog::init(XLAT("stereo vision config"));
string modenames[4] = { "OFF", "anaglyph", "stereo", "ODS" };
dialog::addSelItem(XLAT("stereo mode"), XLAT(modenames[stereo::mode]), 'm');
dialog::addSelItem(XLAT("interpupilar distance"), fts3(stereo::ipd), 'e');
switch(stereo::mode) {
case stereo::sAnaglyph:
dialog::addSelItem(XLAT("distance between images"), fts(stereo::anaglyph_eyewidth), 'd');
break;
case stereo::sLR:
dialog::addSelItem(XLAT("distance between images"), fts(stereo::lr_eyewidth), 'd');
break;
default:
dialog::addBreak(100);
break;
}
dialog::addSelItem(XLAT("field of view"), fts(stereo::fov) + "°", 'f');
dialog::addItem(XLAT("exit stereo configuration"), 'v');
dialog::display();
keyhandler = [] (int sym, int uni) {
using namespace geom3;
dialog::handleNavigation(sym, uni);
if(uni == 'm')
{ stereo::mode = stereo::eStereo((1 + stereo::mode) % 3); return; }
else if(uni == 'e')
dialog::editNumber(stereo::ipd, -10, 10, 0.01, 0, XLAT("interpupilar distance"),
XLAT("Watch the Minkowski hyperboloid or the hypersian rug mode with the "
"red/cyan 3D glasses."));
else if(uni == 'd' && stereo::mode == stereo::sAnaglyph)
dialog::editNumber(stereo::anaglyph_eyewidth, -1, 1, 0.01, 0, XLAT("distance between images"),
XLAT("Watch the Minkowski hyperboloid or the hypersian rug mode with the "
"red/cyan 3D glasses."));
else if(uni == 'd' && stereo::mode == stereo::sLR)
dialog::editNumber(stereo::lr_eyewidth, -1, 1, 0.01, 0, XLAT("distance between images"),
XLAT("Watch the Minkowski hyperboloid or the hypersian rug mode with the "
"red/cyan 3D glasses."));
else if(uni == 'f')
dialog::editNumber(stereo::fov, 1, 170, 1, 45, "field of view",
"Horizontal field of view, in the perspective projection. "
"In the orthogonal projection this just controls the scale."
);
else if(doexiton(sym, uni)) popScreen();
};
}
void show3D() { void show3D() {
cmode = sm::SIDE | sm::A3 | sm::MAYDARK; cmode = sm::SIDE | sm::A3 | sm::MAYDARK;
gamescreen(0); gamescreen(0);
@ -1072,7 +1137,6 @@ void show3D() {
dialog::addBreak(50); dialog::addBreak(50);
dialog::addSelItem(XLAT("Y shift"), fts3(vid.yshift), 'y'); dialog::addSelItem(XLAT("Y shift"), fts3(vid.yshift), 'y');
dialog::addSelItem(XLAT("camera rotation"), fts3(vid.camera_angle), 's'); dialog::addSelItem(XLAT("camera rotation"), fts3(vid.camera_angle), 's');
dialog::addSelItem(XLAT("distance between eyes"), fts3(vid.eye), 'e');
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');
@ -1090,6 +1154,7 @@ void show3D() {
else else
dialog::addInfo(XLAT("parameters set correctly")); dialog::addInfo(XLAT("parameters set correctly"));
dialog::addBreak(50); dialog::addBreak(50);
dialog::addItem(XLAT("stereo vision config"), 'e');
dialog::addItem(XLAT("exit 3D configuration"), 'v'); dialog::addItem(XLAT("exit 3D configuration"), 'v');
dialog::display(); dialog::display();
@ -1121,13 +1186,10 @@ void show3D() {
dialog::editNumber(geom3::rock_wall_ratio, 0, 1, .1, .9, XLAT("Rock-III to wall ratio"), ""); dialog::editNumber(geom3::rock_wall_ratio, 0, 1, .1, .9, XLAT("Rock-III to wall ratio"), "");
else if(uni == 'h') else if(uni == 'h')
dialog::editNumber(geom3::human_wall_ratio, 0, 1, .1, .7, XLAT("Human to wall ratio"), ""); dialog::editNumber(geom3::human_wall_ratio, 0, 1, .1, .7, XLAT("Human to wall ratio"), "");
else if(uni == 'e') else if(uni == 'e')
cmode &= sm::A3, pushScreen(showStereo);
dialog::editNumber(vid.eye, -10, 10, 0.01, 0, XLAT("distance between eyes"),
XLAT("Watch the Minkowski hyperboloid or the hypersian rug mode with the "
"red/cyan 3D glasses."));
else if(uni == 'y') else if(uni == 'y')
cmode &= sm::A3, 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"),

View File

@ -96,7 +96,7 @@ namespace polygonal {
hyperpoint h; hyperpoint h;
h[0] = z2.first * vid.radius; h[0] = z2.first * vid.radius;
h[1] = z2.second * vid.radius; h[1] = z2.second * vid.radius;
h[2] = vid.scrdist; h[2] = stereo::scrdist;
curvepoint(h); curvepoint(h);
} }

View File

@ -430,6 +430,9 @@ void fix_mouseh() {
void handlekey(int sym, int uni) { void handlekey(int sym, int uni) {
if(uni == '=') { stereo::mode = stereo::eStereo((1 + stereo::mode) % 3); return; }
if(uni == '+') switchGL();
if(callhandlers(false, hooks_handleKey, sym, uni)) return; if(callhandlers(false, hooks_handleKey, sym, uni)) return;
keyhandler(sym, uni); keyhandler(sym, uni);

View File

@ -2209,8 +2209,9 @@ void sumaura(int v) {
void drawaura() { void drawaura() {
if(!haveaura()) return; if(!haveaura()) return;
if(stereo::mode) return;
double rad = vid.radius; double rad = vid.radius;
if(sphere && !mdEqui()) rad /= sqrt(vid.alphax*vid.alphax - 1); if(sphere && !mdEqui()) rad /= sqrt(vid.alpha*vid.alpha - 1);
for(int v=0; v<4; v++) sumaura(v); for(int v=0; v<4; v++) sumaura(v);
for(auto& p: auraspecials) { for(auto& p: auraspecials) {
@ -2297,7 +2298,7 @@ void drawaura() {
cx[r][z][u+2] = bak[u] + (aurac[rm][u] / (aurac[rm][3]+.1) - bak[u]) * cmul[z]; cx[r][z][u+2] = bak[u] + (aurac[rm][u] / (aurac[rm][3]+.1) - bak[u]) * cmul[z];
} }
for(int u=0; u<4; u++) glcoords[u][2] = vid.scrdist; for(int u=0; u<4; u++) glcoords[u][2] = stereo::scrdist;
for(int u=0; u<4; u++) coltab[u][3] = 1; for(int u=0; u<4; u++) coltab[u][3] = 1;
for(int r=0; r<AURA; r++) for(int z=0;z<10;z++) { for(int r=0; r<AURA; r++) for(int z=0;z<10;z++) {
@ -2693,7 +2694,7 @@ void setcolors(cell *c, int& wcol, int &fcol) {
fcol = reptilecolor(c); fcol = reptilecolor(c);
break; break;
case laCrossroads: case laCrossroads:
fcol = (vid.goteyes2 ? 0xFF3030 : 0xFF0000); fcol = (stereo::in_anaglyph() ? 0xFF3030 : 0xFF0000);
break; break;
case laCaves: case laEmerald: case laDeadCaves: case laCaves: case laEmerald: case laDeadCaves:
fcol = 0x202020; fcol = 0x202020;
@ -2704,7 +2705,7 @@ void setcolors(cell *c, int& wcol, int &fcol) {
} }
break; break;
case laJungle: case laJungle:
fcol = (vid.goteyes2 ? 0x408040 : 0x008000); fcol = (stereo::in_anaglyph() ? 0x408040 : 0x008000);
break; break;
case laMirror: case laMirrorWall: case laMirrorOld: case laMirror: case laMirrorWall: case laMirrorOld:
fcol = 0x808080; fcol = 0x808080;
@ -2719,10 +2720,10 @@ void setcolors(cell *c, int& wcol, int &fcol) {
if(c->wall == waPlatform) wcol = 0xF0F0A0; if(c->wall == waPlatform) wcol = 0xF0F0A0;
break; break;
case laRlyeh: case laRlyeh:
fcol = (vid.goteyes2 ? 0x4080C0 : 0x004080); fcol = (stereo::in_anaglyph() ? 0x4080C0 : 0x004080);
break; break;
case laHell: case laHell:
fcol = (vid.goteyes2 ? 0xC03030 : 0xC00000); fcol = (stereo::in_anaglyph() ? 0xC03030 : 0xC00000);
break; break;
case laCanvas: case laCanvas:
fcol = c->landparam; fcol = c->landparam;
@ -3166,7 +3167,7 @@ void placeSidewall(cell *c, int i, int sidepar, const transmatrix& V, bool warp,
transmatrix V2 = V * ddspin(c, i); transmatrix V2 = V * ddspin(c, i);
// if(sphere && vid.alphax <= 1 && tC0(V2 * xpush(cellgfxdist(c, i)/2))[2] < -.5) return; // if(sphere && vid.alpha <= 1 && tC0(V2 * xpush(cellgfxdist(c, i)/2))[2] < -.5) return;
/* int aw = away(V2); prio += aw; /* int aw = away(V2); prio += aw;
if(!detaillevel && aw < 0) return; if(!detaillevel && aw < 0) return;
@ -5342,12 +5343,13 @@ void calcparam() {
vid.xcenter += vid.scrsize * vid.xposition; vid.xcenter += vid.scrsize * vid.xposition;
vid.ycenter += vid.scrsize * vid.yposition; vid.ycenter += vid.scrsize * vid.yposition;
ld eye = vid.eye; if(pmodel || rug::rugged) eye = 0; stereo::tanfov = tan(stereo::fov * M_PI / 360);
vid.beta = 1 + vid.alpha + eye;
vid.alphax = vid.alpha + eye; if(pmodel)
vid.goteyes = vid.eye > 0.001 || vid.eye < -0.001; stereo::scrdist = vid.xres / 2 / stereo::tanfov;
vid.goteyes2 = vid.goteyes; else
vid.scrdist = vid.radius; stereo::scrdist = vid.radius;
stereo::scrdist_text = stereo::scrdist;
} }
int ringcolor = darkena(0xFF, 0, 0xFF); int ringcolor = darkena(0xFF, 0, 0xFF);
@ -5360,19 +5362,19 @@ void drawfullmap() {
ptds.clear(); ptds.clear();
if(!vid.goteyes && !euclid && (pmodel == mdDisk || pmodel == mdBall || (sphere && mdEqui()))) { if(!stereo::active() && !euclid && (pmodel == mdDisk || pmodel == mdBall || (sphere && mdEqui()))) {
double rad = vid.radius; double rad = vid.radius;
if(sphere) { if(sphere) {
if(mdEqui()) if(mdEqui())
; ;
else if(!vid.grid && !elliptic) else if(!vid.grid && !elliptic)
rad = 0; rad = 0;
else if(vid.alphax <= 0) else if(vid.alpha <= 0)
; ;
else if(vid.alphax <= 1 && (vid.grid || elliptic)) // mark the equator else if(vid.alpha <= 1 && (vid.grid || elliptic)) // mark the equator
rad = rad * 1 / vid.alphax; rad = rad * 1 / vid.alpha;
else if(vid.grid) // mark the edge else if(vid.grid) // mark the edge
rad /= sqrt(vid.alphax*vid.alphax - 1); rad /= sqrt(vid.alpha*vid.alpha - 1);
} }
if(!haveaura()) queuecircle(vid.xcenter, vid.ycenter, rad, ringcolor, if(!haveaura()) queuecircle(vid.xcenter, vid.ycenter, rad, ringcolor,
vid.usingGL ? PPR_CIRCLE : PPR_OUTCIRCLE); vid.usingGL ? PPR_CIRCLE : PPR_OUTCIRCLE);

131
hud.cpp
View File

@ -332,8 +332,9 @@ bool nofps = false;
void drawStats() { void drawStats() {
callhandlers(false, hooks_prestats); callhandlers(false, hooks_prestats);
#if CAP_ROGUEVIZ #if CAP_ROGUEVIZ
if(rogueviz::on || nohud) return; if(rogueviz::on) return;
#endif #endif
if(nohud || stereo::mode == stereo::sLR) return;
if(viewdists && sidescreen) { if(viewdists && sidescreen) {
distcolors[0] = forecolor; distcolors[0] = forecolor;
dialog::init(""); dialog::init("");
@ -375,11 +376,11 @@ void drawStats() {
{ {
dynamicval<eModel> pm(pmodel, mdDisk); dynamicval<eModel> pm(pmodel, mdDisk);
dynamicval<ld> va(vid.alpha, 1); dynamicval<ld> va(vid.alpha, 1);
dynamicval<ld> vax(vid.alphax, 1); dynamicval<ld> vax(vid.alpha, 1);
dynamicval<videopar> v(vid, vid); dynamicval<videopar> v(vid, vid);
calcparam(); calcparam();
#if CAP_GL #if CAP_GL
selectEyeGL(0); stereo::set_projection(0);
#endif #endif
if(haveMobileCompass()) { if(haveMobileCompass()) {
@ -436,69 +437,77 @@ void drawStats() {
} }
} }
} }
return;
} }
instat = false; else {
bool portrait = vid.xres < vid.yres;
int colspace = portrait ? (vid.yres - vid.xres - vid.fsize*3) : (vid.xres - vid.yres - 16) / 2; instat = false;
int rowspace = portrait ? vid.xres - 16 : vid.yres - vid.fsize * (vid.msgleft ? 9 : 4); bool portrait = vid.xres < vid.yres;
int colid[4], rowid[4]; int colspace = portrait ? (vid.yres - vid.xres - vid.fsize*3) : (vid.xres - vid.yres - 16) / 2;
int maxbyclass[4]; int rowspace = portrait ? vid.xres - 16 : vid.yres - vid.fsize * (vid.msgleft ? 9 : 4);
for(int z=0; z<4; z++) maxbyclass[z] = 0; int colid[4], rowid[4];
for(int i=0; i<glyphs; i++) if(ikappear(i)) int maxbyclass[4];
if(!portrait || (glyphflags(i) | GLYPH_INPORTRAIT)) for(int z=0; z<4; z++) maxbyclass[z] = 0;
maxbyclass[glyphclass(i)]++; for(int i=0; i<glyphs; i++) if(ikappear(i))
int buttonsize; if(!portrait || (glyphflags(i) | GLYPH_INPORTRAIT))
int columns, rows; maxbyclass[glyphclass(i)]++;
bool imponly = false; int buttonsize;
int minsize = vid.fsize * (portrait ? 4 : 2); int columns, rows;
rows = 0; bool imponly = false;
while((buttonsize = minsize - vid.killreduction)) { int minsize = vid.fsize * (portrait ? 4 : 2);
columns = colspace / buttonsize; rows = 0;
rows = rowspace / buttonsize; while((buttonsize = minsize - vid.killreduction)) {
int coltaken = 0; columns = colspace / buttonsize;
for(int z=0; z<4; z++) { rows = rowspace / buttonsize;
if(z == 2 && !portrait) { int coltaken = 0;
if(coltaken > columns) { vid.killreduction++; continue; } for(int z=0; z<4; z++) {
coltaken = 0; if(z == 2 && !portrait) {
if(coltaken > columns) { vid.killreduction++; continue; }
coltaken = 0;
}
colid[z] = coltaken, rowid[z] = 0,
coltaken += (maxbyclass[z] + rows-1) / rows;
} }
colid[z] = coltaken, rowid[z] = 0, if(coltaken > columns) { vid.killreduction++; continue; }
coltaken += (maxbyclass[z] + rows-1) / rows; break;
} }
if(coltaken > columns) { vid.killreduction++; continue; }
break;
}
if(buttonsize <= vid.fsize*3/4) {
imponly = true; buttonsize = minsize;
rows = rowspace / buttonsize; if(!rows) return;
colid[0] = 0; colid[2] = portrait ? 1 : 0;
}
updatesort(); if(buttonsize <= vid.fsize*3/4) {
stable_sort(glyphorder, glyphorder+glyphs, glyphsort); imponly = true; buttonsize = minsize;
rows = rowspace / buttonsize; if(!rows) return;
colid[0] = 0; colid[2] = portrait ? 1 : 0;
}
updatesort();
stable_sort(glyphorder, glyphorder+glyphs, glyphsort);
for(int i0=0; i0<glyphs; i0++) {
int i = glyphorder[i0];
if(!ikappear(i)) continue;
int z = glyphclass(i);
int imp = glyphflags(i);
if(imponly) { z &=~1; if(!(imp & GLYPH_IMPORTANT)) continue; }
for(int i0=0; i0<glyphs; i0++) { int cx, cy;
int i = glyphorder[i0]; if(portrait)
if(!ikappear(i)) continue; cx = 8 + buttonsize * rowid[z], cy = vid.fsize*2 + buttonsize * (colid[z]) + buttonsize/2;
int z = glyphclass(i); else
int imp = glyphflags(i); cx = 8 + buttonsize * (colid[z]), cy = vid.fsize * 3 + buttonsize * rowid[z];
if(imponly) { z &=~1; if(!(imp & GLYPH_IMPORTANT)) continue; }
if(!portrait && z < 2) cx = vid.xres - cx - buttonsize;
int cx, cy;
if(portrait) rowid[z]++; if(rowid[z] >= rows) rowid[z] = 0, colid[z]++;
cx = 8 + buttonsize * rowid[z], cy = vid.fsize*2 + buttonsize * (colid[z]) + buttonsize/2;
else displayglyph2(cx, cy, buttonsize, i);
cx = 8 + buttonsize * (colid[z]), cy = vid.fsize * 3 + buttonsize * rowid[z]; }
if(!portrait && z < 2) cx = vid.xres - cx - buttonsize;
rowid[z]++; if(rowid[z] >= rows) rowid[z] = 0, colid[z]++;
displayglyph2(cx, cy, buttonsize, i);
} }
}
calcparam();
#if CAP_GL
stereo::set_projection(0);
#endif
string s0; string s0;
if(!peace::on) { if(!peace::on) {
if(displayButtonS(vid.xres - 8, vid.fsize, XLAT("score: %1", its(gold())), forecolor, 16, vid.fsize)) { if(displayButtonS(vid.xres - 8, vid.fsize, XLAT("score: %1", its(gold())), forecolor, 16, vid.fsize)) {
@ -554,10 +563,4 @@ XLAT(
callhooks(hooks_stats); callhooks(hooks_stats);
} }
calcparam();
#if CAP_GL
selectEyeGL(0);
#endif
}

31
hyper.h
View File

@ -587,14 +587,13 @@ extern reaction_t help_delegate;
#define HELPFUN(x) (help_delegate = x, "HELPFUN") #define HELPFUN(x) (help_delegate = x, "HELPFUN")
struct videopar { struct videopar {
ld scale, eye, alpha, sspeed, mspeed, yshift, camera_angle; ld scale, alpha, sspeed, mspeed, yshift, camera_angle;
ld ballangle, ballproj; ld ballangle, ballproj;
int mobilecompasssize; int mobilecompasssize;
int aurastr, aurasmoothen; int aurastr, aurasmoothen;
bool full; bool full;
bool goteyes; // for rendering
bool goteyes2; // for choosing colors
int graphglyph; // graphical glyphs int graphglyph; // graphical glyphs
bool darkhepta; bool darkhepta;
int shifttarget; int shifttarget;
@ -609,7 +608,6 @@ struct videopar {
int xcenter, ycenter; int xcenter, ycenter;
int radius; int radius;
int scrsize; int scrsize;
ld alphax, beta;
bool grid; bool grid;
int particles; int particles;
@ -622,9 +620,6 @@ struct videopar {
int msgleft, msglimit; int msgleft, msglimit;
// for OpenGL
float scrdist;
bool usingGL; bool usingGL;
int antialias; int antialias;
#define AA_NOGL 1 #define AA_NOGL 1
@ -2536,3 +2531,25 @@ struct renderbuffer {
void use_as_texture(); void use_as_texture();
void clear(int col); void clear(int col);
}; };
namespace stereo {
enum eStereo { sOFF, sAnaglyph, sLR, sODS };
extern eStereo mode;
extern ld ipd;
extern ld lr_eyewidth, anaglyph_eyewidth;
extern ld fov, tanfov;
extern GLfloat scrdist, scrdist_text;
ld eyewidth();
bool active();
bool in_anaglyph();
void set_viewport(int ed);
void set_projection(int ed);
void set_mask(int ed);
}
double randd();

View File

@ -26,7 +26,7 @@ hyperpoint gethyper(ld x, ld y) {
} }
if(euclid) if(euclid)
return hpxy(hx * (EUCSCALE + vid.alphax), hy * (EUCSCALE + vid.alphax)); return hpxy(hx * (EUCSCALE + vid.alpha), hy * (EUCSCALE + vid.alpha));
if(vid.camera_angle) camrotate(hx, hy); if(vid.camera_angle) camrotate(hx, hy);
@ -45,8 +45,8 @@ hyperpoint gethyper(ld x, ld y) {
ld curv = sphere ? 1 : -1; ld curv = sphere ? 1 : -1;
A = 1+curv*hr; A = 1+curv*hr;
B = 2*hr*vid.alphax*-curv; B = 2*hr*vid.alpha*-curv;
C = 1 - curv*hr*vid.alphax*vid.alphax; C = 1 - curv*hr*vid.alpha*vid.alpha;
// Az^2 - Bz = C // Az^2 - Bz = C
B /= A; C /= A; B /= A; C /= A;
@ -56,13 +56,13 @@ hyperpoint gethyper(ld x, ld y) {
// z = (B/2) + sqrt(C + B^2/4) // z = (B/2) + sqrt(C + B^2/4)
ld rootsign = 1; ld rootsign = 1;
if(sphere && vid.alphax > 1) rootsign = -1; if(sphere && vid.alpha > 1) rootsign = -1;
ld hz = B / 2 + rootsign * sqrt(C + B*B/4); ld hz = B / 2 + rootsign * sqrt(C + B*B/4);
hyperpoint H; hyperpoint H;
H[0] = hx * (hz+vid.alphax); H[0] = hx * (hz+vid.alpha);
H[1] = hy * (hz+vid.alphax); H[1] = hy * (hz+vid.alpha);
H[2] = hz; H[2] = hz;
return H; return H;
@ -83,9 +83,21 @@ void ballmodel(hyperpoint& ret, double alpha, double d, double zl) {
ret[2] = - ax * sa * cb - ay * sb; ret[2] = - ax * sa * cb - ay * sb;
} }
void apply_depth(hyperpoint &f, ld z) {
if(vid.usingGL)
f[2] = z;
else {
z = z * vid.radius;
ld mul = stereo::scrdist / (stereo::scrdist + z);
f[0] = f[0] * mul;
f[1] = f[1] * mul;
f[2] = vid.xres * stereo::eyewidth() / 2 / vid.radius + stereo::ipd * mul / 2;
}
}
void applymodel(hyperpoint H, hyperpoint& ret) { void applymodel(hyperpoint H, hyperpoint& ret) {
ld tz = euclid ? (EUCSCALE+vid.alphax) : vid.alphax+H[2]; ld tz = euclid ? (EUCSCALE+vid.alpha) : vid.alpha+H[2];
if(tz < BEHIND_LIMIT && tz > -BEHIND_LIMIT) tz = BEHIND_LIMIT; if(tz < BEHIND_LIMIT && tz > -BEHIND_LIMIT) tz = BEHIND_LIMIT;
if(pmodel == mdUnchanged) { if(pmodel == mdUnchanged) {
@ -124,9 +136,9 @@ void applymodel(hyperpoint H, hyperpoint& ret) {
if(pmodel == mdDisk) { if(pmodel == mdDisk) {
if(!vid.camera_angle) { if(!vid.camera_angle) {
ret[0] = H[0] / tz; ret[0] = H[0] / tz;
ret[1] = H[1] / tz; ret[1] = H[1] / tz;
ret[2] = (1 - vid.beta / tz); ret[2] = vid.xres / vid.radius * stereo::eyewidth() / 2 - stereo::ipd / tz / 2;
} }
else { else {
ld tx = H[0]; ld tx = H[0];
@ -137,7 +149,7 @@ void applymodel(hyperpoint H, hyperpoint& ret) {
ld ux = tx, uy = ty * cc - ss * tz, uz = tz * cc + ss * ty; ld ux = tx, uy = ty * cc - ss * tz, uz = tz * cc + ss * ty;
ret[0] = ux / uz; ret[0] = ux / uz;
ret[1] = uy / uz; ret[1] = uy / uz;
ret[2] = 1 - vid.beta / uz; ret[2] = vid.xres / vid.radius * stereo::eyewidth() / 2 - stereo::ipd / uz / 2;
} }
return; return;
} }
@ -164,14 +176,14 @@ void applymodel(hyperpoint H, hyperpoint& ret) {
ret[0] = d * H[0] / rad / M_PI; ret[0] = d * H[0] / rad / M_PI;
ret[1] = d * H[1] / rad / M_PI; ret[1] = d * H[1] / rad / M_PI;
ret[2] = 0; ret[2] = 0;
if(zlev != 1 && vid.goteyes) if(zlev != 1 && stereo::active())
ret[2] = geom3::factor_to_lev(zlev); apply_depth(ret, -geom3::factor_to_lev(zlev));
ghcheck(ret,H); ghcheck(ret,H);
return; return;
} }
tz = H[2]+vid.alphax; tz = H[2]+vid.alpha;
if(pmodel == mdPolygonal || pmodel == mdPolynomial) { if(pmodel == mdPolygonal || pmodel == mdPolynomial) {
pair<long double, long double> p = polygonal::compute(H[0]/tz, H[1]/tz); pair<long double, long double> p = polygonal::compute(H[0]/tz, H[1]/tz);
@ -198,8 +210,8 @@ void applymodel(hyperpoint H, hyperpoint& ret) {
if(wmspatial || mmspatial) y0 *= zlev; if(wmspatial || mmspatial) y0 *= zlev;
ret[1] = 1 - y0; ret[1] = 1 - y0;
ret[2] = 0; ret[2] = 0;
if(zlev != 1 && vid.goteyes) if(zlev != 1 && stereo::active())
ret[2] = y0 * geom3::factor_to_lev(zlev); apply_depth(ret, -y0 * geom3::factor_to_lev(zlev));
ghcheck(ret,H); ghcheck(ret,H);
return; return;
} }
@ -229,8 +241,8 @@ void applymodel(hyperpoint H, hyperpoint& ret) {
ret[1] = -y0/M_PI*2; ret[1] = -y0/M_PI*2;
ret[2] = 0; ret[2] = 0;
if(zlev != 1 && vid.goteyes) if(zlev != 1 && stereo::active())
ret[2] = geom3::factor_to_lev(zlev) / (1 + yv * yv); apply_depth(ret, -geom3::factor_to_lev(zlev) / (1 + yv * yv));
ghcheck(ret,H); ghcheck(ret,H);
} }
@ -442,7 +454,7 @@ void drawEuclidean() {
transmatrix View0 = View; transmatrix View0 = View;
ld cellrad = vid.radius / (EUCSCALE + vid.alphax); ld cellrad = vid.radius / (EUCSCALE + vid.alpha);
ld centerd = matrixnorm(View0); ld centerd = matrixnorm(View0);
@ -613,8 +625,8 @@ void fullcenter() {
transmatrix screenpos(ld x, ld y) { transmatrix screenpos(ld x, ld y) {
transmatrix V = Id; transmatrix V = Id;
V[0][2] += (x - vid.xcenter) / vid.radius * (1+vid.alphax); V[0][2] += (x - vid.xcenter) / vid.radius * (1+vid.alpha);
V[1][2] += (y - vid.ycenter) / vid.radius * (1+vid.alphax); V[1][2] += (y - vid.ycenter) / vid.radius * (1+vid.alpha);
return V; return V;
} }
@ -625,7 +637,7 @@ transmatrix atscreenpos(ld x, ld y, ld size) {
V[1][2] += (y - vid.ycenter); V[1][2] += (y - vid.ycenter);
V[0][0] = size * 2 * hcrossf / crossf; V[0][0] = size * 2 * hcrossf / crossf;
V[1][1] = size * 2 * hcrossf / crossf; V[1][1] = size * 2 * hcrossf / crossf;
V[2][2] = vid.scrdist; V[2][2] = stereo::scrdist;
if(euclid) V[2][2] /= EUCSCALE; if(euclid) V[2][2] /= EUCSCALE;
return V; return V;

View File

@ -184,13 +184,13 @@ void addpoint(const hyperpoint& H) {
if(qglcoords >= POLYMAX) return; if(qglcoords >= POLYMAX) return;
if(true) { if(true) {
hyperpoint Hscr; hyperpoint Hscr;
applymodel(H, Hscr); applymodel(H, Hscr);
if(vid.alphax + H[2] <= BEHIND_LIMIT && pmodel == mdDisk) poly_flags |= POLY_BEHIND; if(vid.alpha + H[2] <= BEHIND_LIMIT && pmodel == mdDisk) poly_flags |= POLY_BEHIND;
if(spherespecial) { if(spherespecial) {
double curnorm = H[0]*H[0]+H[1]*H[1]+H[2]*H[2]; double curnorm = H[0]*H[0]+H[1]*H[1]+H[2]*H[2];
double horizon = curnorm / vid.alphax; double horizon = curnorm / vid.alpha;
if((spherespecial>0) ^ (H[2] <= -horizon)) poly_flags |= POLY_INFRONT; if((spherespecial>0) ^ (H[2] <= -horizon)) poly_flags |= POLY_INFRONT;
else { else {
@ -198,7 +198,7 @@ void addpoint(const hyperpoint& H) {
(sqrt(curnorm - horizon*horizon) / (vid.alpha - horizon)) / (sqrt(curnorm - horizon*horizon) / (vid.alpha - horizon)) /
(sqrt(curnorm - H[2]*H[2]) / (vid.alpha+H[2])); (sqrt(curnorm - H[2]*H[2]) / (vid.alpha+H[2]));
// double coef = (vid.alphax + horizon) / (vid.alphax + H[2]); -< that one has a funny effect, seriously // double coef = (vid.alpha + horizon) / (vid.alpha + H[2]); -< that one has a funny effect, seriously
Hscr[0] *= coef; Hscr[0] *= coef;
Hscr[1] *= coef; Hscr[1] *= coef;
} }
@ -218,13 +218,11 @@ void addpoint(const hyperpoint& H) {
void coords_to_poly() { void coords_to_poly() {
polyi = qglcoords; polyi = qglcoords;
for(int i=0; i<polyi; i++) { for(int i=0; i<polyi; i++) {
// printf("%lf %lf\n", double(glcoords[i][0]), double(glcoords[i][1])); // printf("%lf %lf\n", double(glcoords[i][0]), double(glcoords[i][1]));
ld x = vid.xcenter + glcoords[i][0];
ld y = vid.ycenter + glcoords[i][1]; polyx[i] = vid.xcenter + glcoords[i][0] - glcoords[i][2];
ld xe = glcoords[i][2] * vid.eye; polyxr[i] = vid.xcenter + glcoords[i][0] + glcoords[i][2];
polyx[i] = x-xe; polyy[i] = vid.ycenter + glcoords[i][1];
polyxr[i] = x+xe;
polyy[i] = y;
} }
} }
@ -321,15 +319,15 @@ int tinfshift;
void gldraw(int useV, const transmatrix& V, int ps, int pq, int col, int outline, int flags, textureinfo *tinf) { void gldraw(int useV, const transmatrix& V, int ps, int pq, int col, int outline, int flags, textureinfo *tinf) {
if(tinf) { if(tinf) {
glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, tinf->texture_id); glBindTexture(GL_TEXTURE_2D, tinf->texture_id);
glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(3, GL_FLOAT, 0, &tinf->tvertices[tinfshift]); glTexCoordPointer(3, GL_FLOAT, 0, &tinf->tvertices[tinfshift]);
} }
for(int ed = vid.goteyes ? -1 : 0; ed<2; ed+=2) { for(int ed = stereo::active() ? -1 : 0; ed<2; ed+=2) {
if(ed) selectEyeGL(ed); if(ed) stereo::set_projection(ed), stereo::set_viewport(ed);
bool draw = col; bool draw = col;
again: again:
@ -338,7 +336,8 @@ void gldraw(int useV, const transmatrix& V, int ps, int pq, int col, int outline
glPushMatrix(); glPushMatrix();
glapplymatrix(V); glapplymatrix(V);
} }
/*
if(useV == 2) { if(useV == 2) {
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
glPushMatrix(); glPushMatrix();
@ -348,7 +347,7 @@ void gldraw(int useV, const transmatrix& V, int ps, int pq, int col, int outline
0, 0, 1, 0, 0, 0, 1, 0,
0, 0, 0, 1 0, 0, 0, 1
}; };
mat[8] += ed * vid.eye; // EYETODO mat[8] += ed * vid.eye;
glMultMatrixf(mat); glMultMatrixf(mat);
} }
@ -359,11 +358,11 @@ void gldraw(int useV, const transmatrix& V, int ps, int pq, int col, int outline
1, 0, 0, 0, 1, 0, 0, 0,
0, 1, 0, 0, 0, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, vid.scrdist, 1 0, 0, stereo::scrdist, 1
}; };
mat[8] += ed * vid.eye; // EYETODO mat[8] += ed * vid.eye;
glMultMatrixf(mat); glMultMatrixf(mat);
} } */
if(draw) { if(draw) {
glEnable(GL_STENCIL_TEST); glEnable(GL_STENCIL_TEST);
@ -375,15 +374,15 @@ void gldraw(int useV, const transmatrix& V, int ps, int pq, int col, int outline
glDrawArrays(tinf ? GL_TRIANGLES : GL_TRIANGLE_FAN, ps, pq); glDrawArrays(tinf ? GL_TRIANGLES : GL_TRIANGLE_FAN, ps, pq);
if(flags & POLY_INVERSE) { if(flags & POLY_INVERSE) {
selectEyeMask(ed); stereo::set_mask(ed);
glcolor2(col); glcolor2(col);
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;
GLfloat yy = vid.yres; GLfloat yy = vid.yres;
GLfloat scr[12] = { GLfloat scr[12] = {
-xx, -yy, vid.scrdist, +xx, -yy, vid.scrdist, -xx, -yy, stereo::scrdist, +xx, -yy, stereo::scrdist,
+xx, +yy, vid.scrdist, -xx, +yy, vid.scrdist +xx, +yy, stereo::scrdist, -xx, +yy, stereo::scrdist
}; };
GLfloat *cur = currentvertices; GLfloat *cur = currentvertices;
activateVertexArray(scr, 4); activateVertexArray(scr, 4);
@ -393,7 +392,7 @@ void gldraw(int useV, const transmatrix& V, int ps, int pq, int col, int outline
draw = false; goto again; draw = false; goto again;
} }
else { else {
selectEyeMask(ed); stereo::set_mask(ed);
glcolor2(col); glcolor2(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);
@ -410,6 +409,8 @@ void gldraw(int useV, const transmatrix& V, int ps, int pq, int col, int outline
if(useV) glPopMatrix(); if(useV) glPopMatrix();
} }
if(stereo::active()) stereo::set_projection(0), stereo::set_viewport(0), stereo::set_mask(0);
if(tinf) { if(tinf) {
glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY);
@ -422,7 +423,7 @@ void gldraw(int useV, const transmatrix& V, int ps, int pq, int col, int outline
double linewidthat(const hyperpoint& h, double minwidth) { double linewidthat(const hyperpoint& h, double minwidth) {
if(vid.antialias & AA_LINEWIDTH) { if(vid.antialias & AA_LINEWIDTH) {
double dz = h[2]; double dz = h[2];
if(dz < 1 || abs(dz-vid.scrdist) < 1e-6) return vid.linewidth; if(dz < 1 || abs(dz-stereo::scrdist) < 1e-6) return vid.linewidth;
else { else {
double dx = sqrt(dz * dz - 1); double dx = sqrt(dz * dz - 1);
double dfc = dx/(dz+1); double dfc = dx/(dz+1);
@ -576,7 +577,7 @@ void drawpolyline(polytodraw& p) {
/* pp.outline = 0x80808080; /* pp.outline = 0x80808080;
p.col = 0; */ p.col = 0; */
addpoly(pp.V, pp.tab, pp.cnt); addpoly(pp.V, pp.tab, pp.cnt);
mercator_loop_min = mercator_loop_max = 0; mercator_loop_min = mercator_loop_max = 0;
@ -587,7 +588,7 @@ void drawpolyline(polytodraw& p) {
if(poly_flags & POLY_BEHIND) return; if(poly_flags & POLY_BEHIND) return;
for(int i=0; i<qglcoords; i++) { if(0) for(int i=0; i<qglcoords; i++) {
if(abs(glcoords[i][0]) > poly_limit || abs(glcoords[i][1]) > poly_limit) if(abs(glcoords[i][0]) > poly_limit || abs(glcoords[i][1]) > poly_limit)
return; // too large! return; // too large!
} }
@ -604,7 +605,7 @@ void drawpolyline(polytodraw& p) {
poly_flags ^= POLY_INVERSE; poly_flags ^= POLY_INVERSE;
if(poly_flags & POLY_INVERSE) { if(poly_flags & POLY_INVERSE) {
if(curradius < vid.alphax - 1e-6) return; if(curradius < vid.alpha - 1e-6) return;
} }
} }
else poly_flags &=~ POLY_INVERSE; else poly_flags &=~ POLY_INVERSE;
@ -629,7 +630,7 @@ void drawpolyline(polytodraw& p) {
ld a = i * M_PI / 180 + h; ld a = i * M_PI / 180 + h;
glcoords[qglcoords][0] = vid.radius * sin(a); glcoords[qglcoords][0] = vid.radius * sin(a);
glcoords[qglcoords][1] = vid.radius * cos(a); glcoords[qglcoords][1] = vid.radius * cos(a);
glcoords[qglcoords][2] = vid.scrdist; glcoords[qglcoords][2] = stereo::scrdist;
qglcoords++; qglcoords++;
} }
poly_flags ^= POLY_INVERSE; poly_flags ^= POLY_INVERSE;
@ -637,7 +638,7 @@ void drawpolyline(polytodraw& p) {
#if CAP_GL #if CAP_GL
if(vid.usingGL) { if(vid.usingGL) {
// if(pmodel == 0) for(int i=0; i<qglcoords; i++) glcoords[i][2] = vid.scrdist; // if(pmodel == 0) for(int i=0; i<qglcoords; i++) glcoords[i][2] = stereo::scrdist;
if(pp.tinf && (poly_flags & POLY_INVERSE)) { if(pp.tinf && (poly_flags & POLY_INVERSE)) {
return; return;
} }
@ -685,12 +686,12 @@ void drawpolyline(polytodraw& p) {
else else
filledPolygonColorI(s, polyx, polyy, polyi, p.col); filledPolygonColorI(s, polyx, polyy, polyi, p.col);
if(vid.goteyes) filledPolygonColorI(aux, polyxr, polyy, polyi, p.col); if(stereo::active()) filledPolygonColorI(aux, polyxr, polyy, polyi, p.col);
// part(pp.outline, 0) = part(pp.outline, 0) * linewidthat(tC0(pp.V), pp.minwidth); // part(pp.outline, 0) = part(pp.outline, 0) * linewidthat(tC0(pp.V), pp.minwidth);
((vid.antialias & AA_NOGL) ?aapolylineColor:polylineColor)(s, polyx, polyy, polyi, pp.outline); ((vid.antialias & AA_NOGL) ?aapolylineColor:polylineColor)(s, polyx, polyy, polyi, pp.outline);
if(vid.goteyes) aapolylineColor(aux, polyxr, polyy, polyi, pp.outline); if(stereo::active()) aapolylineColor(aux, polyxr, polyy, polyi, pp.outline);
if(vid.xres >= 2000 || fatborder) { if(vid.xres >= 2000 || fatborder) {
int xmi = 3000, xma = -3000; int xmi = 3000, xma = -3000;
@ -808,20 +809,6 @@ void drawqueueitem(polytodraw& ptd) {
#endif #endif
drawCircle(ptd.u.cir.x, ptd.u.cir.y, ptd.u.cir.size, ptd.col); drawCircle(ptd.u.cir.x, ptd.u.cir.y, ptd.u.cir.size, ptd.col);
} }
#if CAP_SDL
if(vid.goteyes && !vid.usingGL) {
int qty = s->w * s->h;
int *a = (int*) s->pixels;
int *b = (int*) aux->pixels;
SDL_LockSurface(aux);
while(qty) {
*a = ((*a) & 0xFF0000) | ((*b) & 0x00FFFF);
a++; b++; qty--;
}
SDL_UnlockSurface(aux);
}
#endif
} }
void initquickqueue() { void initquickqueue() {
@ -905,7 +892,7 @@ void drawqueue() {
profile_stop(3); profile_stop(3);
#if CAP_SDL #if CAP_SDL
if(vid.goteyes && !vid.usingGL) { if(stereo::active() && !vid.usingGL) {
if(aux && (aux->w != s->w || aux->h != s->h)) if(aux && (aux->w != s->w || aux->h != s->h))
SDL_FreeSurface(aux); SDL_FreeSurface(aux);
@ -965,7 +952,30 @@ void drawqueue() {
} }
#if CAP_GL #if CAP_GL
if(vid.goteyes && vid.usingGL) selectEyeGL(0), selectEyeMask(0); if(vid.usingGL)
stereo::set_projection(0), stereo::set_mask(0), stereo::set_viewport(0);
#endif
#if CAP_SDL
if(stereo::mode == stereo::sAnaglyph && !vid.usingGL) {
int qty = s->w * s->h;
int *a = (int*) s->pixels;
int *b = (int*) aux->pixels;
SDL_LockSurface(aux);
while(qty) {
*a = ((*a) & 0xFF0000) | ((*b) & 0x00FFFF);
a++; b++; qty--;
}
SDL_UnlockSurface(aux);
}
if(stereo::mode == stereo::sLR && !vid.usingGL) {
SDL_LockSurface(aux);
for(int y=0; y<vid.yres; y++)
for(int x=vid.xres/2; x<vid.xres; x++)
qpixel(s,x,y) = qpixel(aux,x,y);
SDL_UnlockSurface(aux);
}
#endif #endif
setcameraangle(false); setcameraangle(false);
@ -2707,7 +2717,8 @@ void getcoord0(const hyperpoint& h, int& xc, int &yc, int &sc) {
applymodel(h, hscr); applymodel(h, hscr);
xc = vid.xcenter + vid.radius * hscr[0]; xc = vid.xcenter + vid.radius * hscr[0];
yc = vid.ycenter + vid.radius * hscr[1]; yc = vid.ycenter + vid.radius * hscr[1];
sc = vid.eye * vid.radius * hscr[2]; sc = 0;
// EYETODO sc = vid.eye * vid.radius * hscr[2];
} }
void queuechr(const hyperpoint& h, int size, char chr, int col, int frame = 0) { void queuechr(const hyperpoint& h, int size, char chr, int col, int frame = 0) {

136
rug.cpp
View File

@ -19,8 +19,6 @@ bool good_shape;
ld modelscale = 1; ld modelscale = 1;
ld model_distance = 2; ld model_distance = 2;
ld fov = 90;
eGeometry gwhere = gEuclid; eGeometry gwhere = gEuclid;
#define USING_NATIVE_GEOMETRY dynamicval<eGeometry> gw(geometry, gwhere == gElliptic ? gSphere : gwhere) #define USING_NATIVE_GEOMETRY dynamicval<eGeometry> gw(geometry, gwhere == gElliptic ? gSphere : gwhere)
@ -55,6 +53,7 @@ struct rugpoint {
double dist; double dist;
hyperpoint h; // point in the represented space hyperpoint h; // point in the represented space
hyperpoint flat; // point in the native space, in azeq hyperpoint flat; // point in the native space, in azeq
hyperpoint precompute;
vector<edge> edges; vector<edge> edges;
// Find-Union algorithm // Find-Union algorithm
rugpoint *glue; rugpoint *glue;
@ -202,7 +201,7 @@ rugpoint *addRugpoint(hyperpoint h, double dist) {
m->h = h; m->h = h;
/* /*
ld tz = vid.alphax+h[2]; ld tz = vid.alpha+h[2];
m->x1 = (1 + h[0] / tz) / 2; m->x1 = (1 + h[0] / tz) / 2;
m->y1 = (1 + h[1] / tz) / 2; m->y1 = (1 + h[1] / tz) / 2;
*/ */
@ -345,7 +344,7 @@ void setVidParam() {
vid.xres = vid.yres = TEXTURESIZE; vid.xres = vid.yres = TEXTURESIZE;
vid.scrsize = HTEXTURESIZE; vid.scrsize = HTEXTURESIZE;
vid.radius = vid.scrsize * vid.scale; vid.xcenter = HTEXTURESIZE; vid.ycenter = HTEXTURESIZE; vid.radius = vid.scrsize * vid.scale; vid.xcenter = HTEXTURESIZE; vid.ycenter = HTEXTURESIZE;
vid.beta = 2; vid.alphax = 1; vid.eye = 0; vid.goteyes = false; vid.alpha = 1;
} }
void buildTorusRug() { void buildTorusRug() {
@ -899,11 +898,11 @@ void physics() {
// drawing the Rug // drawing the Rug
//----------------- //-----------------
int eyemod; bool use_precompute;
void getco(rugpoint *m, hyperpoint& h, int &spherepoints) { void getco(rugpoint *m, hyperpoint& h, int &spherepoints) {
using namespace hyperpoint_vec; using namespace hyperpoint_vec;
h = m->getglue()->flat; h = use_precompute ? m->getglue()->precompute : m->getglue()->flat;
if(rug_perspective && gwhere >= gSphere) { if(rug_perspective && gwhere >= gSphere) {
if(h[2] > 0) { if(h[2] > 0) {
ld rad = hypot3(h); ld rad = hypot3(h);
@ -916,7 +915,6 @@ void getco(rugpoint *m, hyperpoint& h, int &spherepoints) {
spherepoints++; spherepoints++;
} }
} }
if(eyemod) h[0] += eyemod * h[2] * vid.eye;
} }
extern int besti; extern int besti;
@ -938,7 +936,6 @@ ld raddif(ld a, ld b) {
} }
bool ods = false; bool ods = false;
ld ipd = 0.05;
bool project_ods(hyperpoint azeq, hyperpoint& h1, hyperpoint& h2, bool eye) { bool project_ods(hyperpoint azeq, hyperpoint& h1, hyperpoint& h2, bool eye) {
ld tanalpha = tan(ipd/2); ld tanalpha = tan(ipd/2);
@ -1067,6 +1064,7 @@ void prepareTexture() {
videopar svid = vid; videopar svid = vid;
setVidParam(); setVidParam();
dynamicval<stereo::eStereo> d(stereo::mode, stereo::sOFF);
glbuf->enable(); glbuf->enable();
@ -1113,12 +1111,6 @@ void drawRugScene() {
glbuf->use_as_texture(); glbuf->use_as_texture();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if(backcolor == 0) if(backcolor == 0)
glClearColor(0.05,0.05,0.05,1); glClearColor(0.05,0.05,0.05,1);
else else
@ -1131,60 +1123,59 @@ void drawRugScene() {
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS); glDepthFunc(GL_LESS);
ld tanfov = tan(fov * M_PI / 360); for(int ed=stereo::active() && stereo::mode != stereo::sODS ? -1 : 0; ed < 2; ed += 2) {
use_precompute = false;
stereo::set_mask(ed), stereo::set_viewport(ed);
if(ed == 1 && stereo::mode == stereo::sAnaglyph)
glClear(GL_DEPTH_BUFFER_BIT);
start_projection(ed);
if(stereo::mode == stereo::sODS)
glOrtho(-M_PI, M_PI, -M_PI, M_PI, 0, -M_PI * 2);
else if(rug_perspective || stereo::active()) {
ld vnear = .001;
ld vfar = 1000;
ld sca = vnear * stereo::tanfov / vid.xres;
xview = stereo::tanfov;
yview = stereo::tanfov * vid.yres / vid.xres;
glFrustum(-sca * vid.xres, sca * vid.xres, -sca * vid.yres, sca * vid.yres, vnear, vfar);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
if(!rug_perspective) glTranslatef(0, 0, -model_distance);
if(ed) {
if(gwhere == gEuclid)
glTranslatef(stereo::ipd*ed/2, 0, 0);
else {
use_precompute = true;
for(auto p: points) {
p->precompute = p->flat;
push_point(p->precompute, 0, stereo::ipd*ed/2);
}
}
}
}
else {
xview = stereo::tanfov * model_distance;
yview = stereo::tanfov * model_distance * vid.yres / vid.xres;
glOrtho(-xview, xview, yview, -yview, -1000, 1000);
}
glColor4f(1.f, 1.f, 1.f, 1.f);
#if CAP_ODS if(rug_perspective && gwhere >= gSphere) {
if(ods) { glEnable(GL_FOG);
glOrtho(-M_PI, M_PI, -M_PI, M_PI, 0, -M_PI * 2); glFogi(GL_FOG_MODE, GL_LINEAR);
} glFogf(GL_FOG_START, 0);
else glFogf(GL_FOG_END, gwhere == gSphere ? 10 : 4);
#endif }
if(rug_perspective) {
ld vnear = .001;
ld vfar = 1000;
ld sca = vnear * tanfov / vid.xres;
xview = -tanfov;
yview = -tanfov * vid.yres / vid.xres;
glFrustum(-sca * vid.xres, sca * vid.xres, -sca * vid.yres, sca * vid.yres, vnear, vfar);
}
else {
xview = tanfov * model_distance;
yview = tanfov * model_distance * vid.yres / vid.xres;
glOrtho(-xview, xview, -yview, yview, -1000, 1000);
}
glColor4f(1.f, 1.f, 1.f, 1.f);
if(rug_perspective && gwhere >= gSphere) {
glEnable(GL_FOG);
glFogi(GL_FOG_MODE, GL_LINEAR);
glFogf(GL_FOG_START, 0);
glFogf(GL_FOG_END, gwhere == gSphere ? 10 : 4);
}
if(vid.eye > .001 || vid.eye < -.001) {
selectEyeMask(1);
glClear(GL_DEPTH_BUFFER_BIT);
glBegin(GL_TRIANGLES);
eyemod = 1;
for(int t=0; t<size(triangles); t++)
drawTriangle(triangles[t]);
glEnd();
selectEyeMask(-1);
eyemod = -1;
glClear(GL_DEPTH_BUFFER_BIT);
glBegin(GL_TRIANGLES);
for(int t=0; t<size(triangles); t++)
drawTriangle(triangles[t]);
glEnd();
selectEyeMask(0);
}
else {
glBegin(GL_TRIANGLES); glBegin(GL_TRIANGLES);
for(int t=0; t<size(triangles); t++) for(int t=0; t<size(triangles); t++)
drawTriangle(triangles[t]); drawTriangle(triangles[t]);
glEnd(); glEnd();
stereo::set_mask(0);
} }
glDisable(GL_TEXTURE_2D); glDisable(GL_TEXTURE_2D);
@ -1193,9 +1184,8 @@ void drawRugScene() {
glEnable(GL_BLEND); glEnable(GL_BLEND);
glDisable(GL_FOG); glDisable(GL_FOG);
glMatrixMode(GL_PROJECTION); stereo::set_mask(0), stereo::set_viewport(0);
glLoadIdentity(); stereo::set_projection(0);
selectEyeGL(0);
need_mouseh = true; need_mouseh = true;
} }
@ -1494,7 +1484,7 @@ void show() {
dialog::addSelItem(XLAT("model scale factor"), fts(modelscale), 'm'); dialog::addSelItem(XLAT("model scale factor"), fts(modelscale), 'm');
if(rug::rugged) if(rug::rugged)
dialog::addSelItem(XLAT("model iterations"), its(queueiter), 0); dialog::addSelItem(XLAT("model iterations"), its(queueiter), 0);
dialog::addSelItem(XLAT("field of view"), fts(fov) + "°", 'f'); dialog::addItem(XLAT("stereo vision config"), 'f');
// dialog::addSelItem(XLAT("protractor"), fts(protractor * 180 / M_PI) + "°", 'f'); // dialog::addSelItem(XLAT("protractor"), fts(protractor * 180 / M_PI) + "°", 'f');
if(!good_shape) { if(!good_shape) {
dialog::addSelItem(XLAT("maximum error"), ftsg(err_zero), 'e'); dialog::addSelItem(XLAT("maximum error"), ftsg(err_zero), 'e');
@ -1591,12 +1581,8 @@ void show() {
dialog::scaleLog(); dialog::scaleLog();
dialog::reaction = [] () { err_zero_current = err_zero; }; dialog::reaction = [] () { err_zero_current = err_zero; };
} }
else if(uni == 'f') { else if(uni == 'f')
dialog::editNumber(fov, 1, 170, 1, 45, "field of view", pushScreen(showStereo);
"Horizontal field of view, in the perspective projection. "
"In the orthogonal projection this just controls the scale."
);
}
else if(uni == 'n' && !rug::rugged) else if(uni == 'n' && !rug::rugged)
gwhere = eGeometry((gwhere+1) % 4); gwhere = eGeometry((gwhere+1) % 4);
#if !ISPANDORA #if !ISPANDORA
@ -1648,6 +1634,10 @@ int rugArgs() {
shift(); vertex_limit = argi(); shift(); vertex_limit = argi();
} }
else if(argis("-rugon")) {
PHASE(3); rug::init();
}
#if CAP_ODS #if CAP_ODS
else if(argis("-ods")) { else if(argis("-ods")) {
ods = true; ods = true;

View File

@ -1525,7 +1525,7 @@ void movePlayer(monster *m, int delta) {
hyperpoint jh = hpxy(mdx/100.0, mdy/100.0); hyperpoint jh = hpxy(mdx/100.0, mdy/100.0);
hyperpoint ctr = m->pat * C0; hyperpoint ctr = m->pat * C0;
if(sphere && vid.alphax > 1.001) for(int i=0; i<3; i++) ctr[i] = -ctr[i]; if(sphere && vid.alpha > 1.001) for(int i=0; i<3; i++) ctr[i] = -ctr[i];
hyperpoint h = inverse(m->pat) * rgpushxto0(ctr) * jh; hyperpoint h = inverse(m->pat) * rgpushxto0(ctr) * jh;

View File

@ -467,7 +467,7 @@ void drawRawTexture() {
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
glcolor2(0xFFFFFF20); glcolor2(0xFFFFFF20);
glPushMatrix(); glPushMatrix();
glTranslatef(0, 0, vid.scrdist); glTranslatef(0, 0, stereo::scrdist);
glBindTexture(GL_TEXTURE_2D, textureid); glBindTexture(GL_TEXTURE_2D, textureid);
vector<GLfloat> tver, sver; vector<GLfloat> tver, sver;
for(int i=0; i<4; i++) { for(int i=0; i<4; i++) {