improved hyperboloid model

This commit is contained in:
Zeno Rogue 2018-10-23 20:08:57 +02:00
parent 0d4ab71115
commit 8a37a43547
6 changed files with 110 additions and 22 deletions

View File

@ -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) {

View File

@ -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') {

View File

@ -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
}

View File

@ -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)

View File

@ -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);

View File

@ -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,9 +1358,12 @@ 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
if(vid.usingGL)
stereo::set_projection(0), stereo::set_mask(0), stereo::set_viewport(0);