mirror of
https://github.com/zenorogue/hyperrogue.git
synced 2024-12-20 23:50:27 +00:00
improved hyperboloid model
This commit is contained in:
parent
0d4ab71115
commit
8a37a43547
@ -255,7 +255,7 @@ void stereo::set_viewport(int ed) {
|
||||
}
|
||||
|
||||
bool model_needs_depth() {
|
||||
return pmodel == mdBall || pmodel == mdHyperboloid || pmodel == mdHemisphere;
|
||||
return pmodel == mdBall || pmodel == mdHemisphere;
|
||||
}
|
||||
|
||||
void setGLProjection(color_t col) {
|
||||
|
@ -297,6 +297,7 @@ namespace conformal {
|
||||
ld model_orientation, halfplane_scale;
|
||||
ld ocos, osin;
|
||||
bool model_straight;
|
||||
ld top_z = 5;
|
||||
|
||||
bool autoband = false;
|
||||
bool autobandhistory = false;
|
||||
@ -658,6 +659,9 @@ namespace conformal {
|
||||
dialog::addSelItem(XLAT("camera rotation in 3D models"), fts3(vid.ballangle), 'b');
|
||||
}
|
||||
|
||||
if(pmodel == mdHyperboloid)
|
||||
dialog::addSelItem(XLAT("topz"), fts3(top_z), 'l');
|
||||
|
||||
if(pmodel == mdHemisphere && euclid) {
|
||||
dialog::addSelItem(XLAT("parameter"), fts3(vid.euclid_to_sphere), 'l');
|
||||
}
|
||||
@ -710,6 +714,8 @@ namespace conformal {
|
||||
#endif
|
||||
else if(uni == 'l' && model_has_orientation())
|
||||
dialog::editNumber(model_orientation, 0, 360, 90, 0, XLAT("model orientation"), "");
|
||||
else if(uni == 'l' && pmodel == mdHyperboloid)
|
||||
dialog::editNumber(top_z, 1, 20, 0.25, 4, XLAT("topz"), "");
|
||||
else if(uni == 'b' && pmodel == mdHalfplane)
|
||||
dialog::editNumber(model_orientation, 0, 2, 0.25, 1, XLAT("halfplane scale"), "");
|
||||
else if(uni == 's') {
|
||||
|
44
graph.cpp
44
graph.cpp
@ -5562,15 +5562,43 @@ void drawfullmap() {
|
||||
if(pmodel == mdBall) ballgeometry();
|
||||
}
|
||||
|
||||
if(pmodel == mdHyperboloid) {
|
||||
if(pmodel == mdHyperboloid && hyperbolic) {
|
||||
#if CAP_QUEUE
|
||||
color_t col = darkena(0x80, 0, 0x80);
|
||||
queueline(hpxyz(0,0,1), hpxyz(0,0,-vid.alpha), col, 0, PPR::CIRCLE);
|
||||
queueline(xpush0(+4), hpxyz(0,0,0), col, 0, PPR::CIRCLE);
|
||||
queueline(xpush0(+4), hpxyz(0,0,-vid.alpha), col, 0, PPR::CIRCLE);
|
||||
queueline(xpush0(-4), hpxyz(0,0,0), col, 0, PPR::CIRCLE);
|
||||
queueline(xpush0(-4), hpxyz(0,0,-vid.alpha), col, 0, PPR::CIRCLE);
|
||||
queueline(hpxyz(-1,0,0), hpxyz(1,0,0), col, 0, PPR::CIRCLE);
|
||||
curvepoint(hpxyz(0,0,1));
|
||||
curvepoint(hpxyz(0,0,-vid.alpha));
|
||||
queuecurve(ringcolor, 0, PPR::CIRCLE);
|
||||
|
||||
ld& tz = conformal::top_z;
|
||||
ld z = acosh(tz);
|
||||
|
||||
hyperpoint a = xpush0(z);
|
||||
ld ball = -vid.ballangle * M_PI / 180;
|
||||
ld cb = cos(ball), sb = sin(ball);
|
||||
|
||||
a[1] = sb * a[2] / -cb;
|
||||
a[0] = sqrt(-1 + a[2] * a[2] - a[1] * a[1]);
|
||||
|
||||
curvepoint(hpxyz(0,0,-vid.alpha));
|
||||
curvepoint(a);
|
||||
curvepoint(hpxyz(0,0,0));
|
||||
a[0] = -a[0];
|
||||
curvepoint(a);
|
||||
curvepoint(hpxyz(0,0,-vid.alpha));
|
||||
queuecurve(ringcolor, 0, PPR::CIRCLE);
|
||||
|
||||
curvepoint(hpxyz(-1,0,0));
|
||||
curvepoint(hpxyz(1,0,0));
|
||||
queuecurve(ringcolor, 0, PPR::CIRCLE);
|
||||
|
||||
a[1] = sb * tz / -cb;
|
||||
a[0] = sqrt(tz * tz - a[1] * a[1]);
|
||||
a[2] = tz - vid.alpha;
|
||||
|
||||
curvepoint(a);
|
||||
curvepoint(hpxyz(0,0,-vid.alpha));
|
||||
a[0] = -a[0];
|
||||
curvepoint(a);
|
||||
queuecurve(ringcolor, 0, PPR::CIRCLE);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
3
hyper.h
3
hyper.h
@ -1265,7 +1265,7 @@ enum eModel {
|
||||
mdEquidistant, mdEquiarea, mdBall, mdHyperboloid,
|
||||
mdHemisphere, mdBandEquidistant, mdBandEquiarea, mdSinusoidal, mdTwoPoint,
|
||||
mdFisheye,
|
||||
mdGUARD, mdUnchanged };
|
||||
mdGUARD, mdUnchanged, mdHyperboloidFlat };
|
||||
|
||||
namespace conformal {
|
||||
extern bool on;
|
||||
@ -1280,6 +1280,7 @@ namespace conformal {
|
||||
extern ld halfplane_scale;
|
||||
extern ld ocos, osin;
|
||||
extern bool model_straight;
|
||||
extern ld top_z;
|
||||
|
||||
// screen coordinates to logical coordinates: apply_orientation(x,y)
|
||||
// logical coordinates back to screen coordinates: apply_orientation(y,x)
|
||||
|
24
hypgraph.cpp
24
hypgraph.cpp
@ -192,7 +192,31 @@ void applymodel(hyperpoint H, hyperpoint& ret) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(pmodel == mdHyperboloidFlat) {
|
||||
H[2] += vid.alpha;
|
||||
H[0] /= H[2];
|
||||
H[1] /= H[2];
|
||||
H[2] = 1 - vid.alpha;
|
||||
|
||||
ld ball = -vid.ballangle * M_PI / 180;
|
||||
ld cb = cos(ball), sb = sin(ball);
|
||||
|
||||
ret[0] = H[0] / 3;
|
||||
ret[1] = (1 - H[2]) / 3 * cb - H[1] / 3 * sb;
|
||||
ret[2] = -(-H[1] / 3 * cb - (1 - H[2]) / 3 * sb);
|
||||
|
||||
ghcheck(ret,H);
|
||||
return;
|
||||
}
|
||||
|
||||
if(pmodel == mdHyperboloid) {
|
||||
ld& tz = conformal::top_z;
|
||||
if(H[2] > tz) {
|
||||
ld scale = sqrt(tz*tz-1) / hypot(H[0], H[1]);
|
||||
H[0] *= scale;
|
||||
H[1] *= scale;
|
||||
H[2] = tz;
|
||||
}
|
||||
|
||||
ld ball = -vid.ballangle * M_PI / 180;
|
||||
ld cb = cos(ball), sb = sin(ball);
|
||||
|
51
polygons.cpp
51
polygons.cpp
@ -183,10 +183,27 @@ bool knowgood;
|
||||
hyperpoint goodpoint;
|
||||
vector<pair<int, hyperpoint>> tofix;
|
||||
|
||||
bool two_sided_model() {
|
||||
if(pmodel == mdHyperboloid) return !euclid;
|
||||
// if(pmodel == mdHemisphere) return true;
|
||||
if(pmodel == mdDisk) return sphere;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool correct_side(const hyperpoint& H) {
|
||||
double curnorm = H[0]*H[0]+H[1]*H[1]+H[2]*H[2];
|
||||
double horizon = curnorm / vid.alpha;
|
||||
return (spherespecial>0) ^ (H[2] <= -horizon);
|
||||
if(pmodel == mdDisk && sphere) {
|
||||
double curnorm = H[0]*H[0]+H[1]*H[1]+H[2]*H[2];
|
||||
double horizon = curnorm / vid.alpha;
|
||||
return (spherespecial>0) ^ (H[2] <= -horizon);
|
||||
}
|
||||
if(pmodel == mdHyperboloid && hyperbolic) {
|
||||
ld ball = -vid.ballangle * M_PI / 180;
|
||||
ld cb = cos(ball), sb = sin(ball);
|
||||
return (spherespecial > 0) ^ (
|
||||
sb * H[2] > -cb * H[1]
|
||||
);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void fixpoint(array<float, 3>& hscr, hyperpoint H) {
|
||||
@ -215,7 +232,7 @@ void addpoint(const hyperpoint& H) {
|
||||
poly_flags |= POLY_INFRONT, last_infront = false;
|
||||
if(!knowgood || (spherespecial > 0 ? H[2]>goodpoint[2] : H[2]<goodpoint[2])) goodpoint = H, knowgood = true;
|
||||
}
|
||||
else if(poly_flags & POLY_ISSIDE) {
|
||||
else if(sphere && (poly_flags & POLY_ISSIDE)) {
|
||||
double curnorm = H[0]*H[0]+H[1]*H[1]+H[2]*H[2];
|
||||
double horizon = curnorm / vid.alpha;
|
||||
poly_flags |= POLY_NOTINFRONT;
|
||||
@ -810,12 +827,12 @@ void dqi_poly::draw() {
|
||||
return;
|
||||
}
|
||||
|
||||
if(spherespecial && prio == PPR::MOBILE_ARROW) {
|
||||
/* if(spherespecial && prio == PPR::MOBILE_ARROW) {
|
||||
if(spherephase == 0) return;
|
||||
dynamicval<int> ss(spherespecial, 0);
|
||||
draw();
|
||||
return;
|
||||
}
|
||||
} */
|
||||
|
||||
#if CAP_GL
|
||||
if(vid.usingGL && using_perspective) {
|
||||
@ -867,7 +884,7 @@ void dqi_poly::draw() {
|
||||
|
||||
if(poly_flags & POLY_NIF_ERROR) return;
|
||||
|
||||
if(spherespecial == 1 && (poly_flags & POLY_INFRONT) && (poly_flags & POLY_NOTINFRONT) && vid.alpha <= 1) {
|
||||
if(spherespecial == 1 && sphere && (poly_flags & POLY_INFRONT) && (poly_flags & POLY_NOTINFRONT) && vid.alpha <= 1) {
|
||||
bool around_center = false;
|
||||
for(int i=0; i<isize(glcoords)-1; i++) {
|
||||
double x1 = glcoords[i][0];
|
||||
@ -882,7 +899,7 @@ void dqi_poly::draw() {
|
||||
if(around_center) return;
|
||||
}
|
||||
|
||||
if((spherespecial > 0 || (sphere && equi)) && !(poly_flags & POLY_ISSIDE)) {
|
||||
if(sphere && (spherespecial > 0 || equi) && !(poly_flags & POLY_ISSIDE)) {
|
||||
|
||||
if(!tinf) {
|
||||
|
||||
@ -1314,7 +1331,14 @@ void drawqueue() {
|
||||
stereo::set_projection(0);
|
||||
|
||||
// on the sphere, parts on the back are drawn first
|
||||
if(sphere && pmodel == 0) {
|
||||
if(two_sided_model()) {
|
||||
|
||||
if(pmodel == mdHyperboloid) {
|
||||
dynamicval dv(pmodel, mdHyperboloidFlat);
|
||||
for(auto& ptd: ptds)
|
||||
if(!among(ptd->prio, PPR::MOBILE_ARROW, PPR::OUTCIRCLE, PPR::CIRCLE))
|
||||
ptd->draw();
|
||||
}
|
||||
|
||||
// in SVG, draw boundary circle first
|
||||
if(svg::in) for(auto& ptd: ptds) ptd->draw_pre();
|
||||
@ -1324,7 +1348,9 @@ void drawqueue() {
|
||||
|
||||
reverse_side_priorities();
|
||||
for(int i=ptds.size()-1; i>=0; i--)
|
||||
ptds[i]->draw_back();
|
||||
if(!among(ptds[i]->prio, PPR::MOBILE_ARROW, PPR::OUTCIRCLE, PPR::CIRCLE))
|
||||
ptds[i]->draw_back();
|
||||
|
||||
glflush();
|
||||
reverse_side_priorities();
|
||||
spherespecial *= -1;
|
||||
@ -1332,7 +1358,10 @@ void drawqueue() {
|
||||
stereo::set_projection(0);
|
||||
}
|
||||
|
||||
for(auto& ptd: ptds) ptd->draw();
|
||||
for(auto& ptd: ptds) {
|
||||
dynamicval<int> ss(spherespecial, among(ptd->prio, PPR::MOBILE_ARROW, PPR::OUTCIRCLE, PPR::CIRCLE) ? 0 : spherespecial);
|
||||
ptd->draw();
|
||||
}
|
||||
glflush();
|
||||
|
||||
#if CAP_GL
|
||||
|
Loading…
Reference in New Issue
Block a user