diff --git a/drawing.cpp b/drawing.cpp index 0992c79a..1fe89f5a 100644 --- a/drawing.cpp +++ b/drawing.cpp @@ -353,10 +353,9 @@ EX int get_side(const hyperpoint& H) { } if(pmodel == mdRotatedHyperboles) return H[1] > 0 ? -1 : 1; - if(pmodel == mdHyperboloid && hyperbolic) - return (models::sin_ball * H[2] > -models::cos_ball * H[1]) ? -1 : 1; - if(pmodel == mdHyperboloid && sphere) - return (models::sin_ball * H[2] > models::cos_ball * H[1]) ? -1 : 1; + if(pmodel == mdHyperboloid) { + return det2(pconf.ball() * cspin90(1, 2) * rgpushxto0(H)) > 0 ? 1 : -1; + } if(pmodel == mdHyperboloidFlat && sphere) return H[2] >= 0 ? 1 : -1; if(pmodel == mdHemisphere && hyperbolic) { @@ -369,8 +368,9 @@ EX int get_side(const hyperpoint& H) { int s = H1[2] > 0 ? 1 : -1; if(hemi_side && s != hemi_side) return -spherespecial; H1[0] /= H1[2]; H1[1] /= H1[2]; - H1[2] = s * sqrt(1 + H1[0]*H1[0] + H1[1] * H1[1]); - return (models::sin_ball * H1[2] > models::cos_ball * H1[1]) ? 1 : -1; + H1[2] = -s * sqrt(1 + H1[0]*H1[0] + H1[1] * H1[1]); + dynamicval g(cginf.g, giHyperb2); + return det2(pconf.ball() * cspin90(1, 2) * rgpushxto0(H1)) > 0 ? 1 : -1; } if(pmodel == mdSpiral && pconf.spiral_cone < 360) { return cone_side(shiftless(H)); @@ -2435,14 +2435,14 @@ EX void draw_main() { } if(pmodel == mdHemisphere && sphere && hemi_side == 0 && !vrhr::rendering()) { - hemi_side = models::sin_ball > 0 ? 1 : -1; + hemi_side = (pconf.ball() * hyperpoint(0,1,0,1)) [2] < 0 ? 1 : -1; draw_main(); if(pconf.show_hyperboloid_flat) { dynamicval dv (pmodel, mdHyperboloidFlat); dynamicval ds (spherespecial, 1); for(auto& ptd: ptds) - if(!among(ptd->prio, PPR::MOBILE_ARROW, PPR::OUTCIRCLE, PPR::CIRCLE)) + if(!among(ptd->prio, PPR::MOBILE_ARROW, PPR::OUTCIRCLE, PPR::CIRCLE)) ptd->draw(); } diff --git a/hypgraph.cpp b/hypgraph.cpp index 7b1b0b5c..fd2ccbad 100644 --- a/hypgraph.cpp +++ b/hypgraph.cpp @@ -162,7 +162,7 @@ void ballmodel(hyperpoint& ret, double alpha, double d, double zl) { ret[1] = ay; ret[2] = ax * sa; - models::apply_ball(ret[2], ret[1]); + ret = pconf.ball() * ret; } bool use_z_coordinate() { @@ -970,7 +970,7 @@ EX void apply_other_model(shiftpoint H_orig, hyperpoint& ret, eModel md) { swap(ret[1], ret[2]); - models::apply_ball(ret[2], ret[1]); + ret = pconf.ball() * ret; break; } @@ -1032,7 +1032,7 @@ EX void apply_other_model(shiftpoint H_orig, hyperpoint& ret, eModel md) { ret[0] = ret[0] / 3; tie(ret[1], ret[2]) = make_pair(((sphere?0:1) - ret[2]) / 3, ret[1] / 3); - models::apply_ball(ret[2], ret[1]); + ret = pconf.ball() * ret; break; } @@ -1443,7 +1443,7 @@ EX void apply_other_model(shiftpoint H_orig, hyperpoint& ret, eModel md) { if(euclid) ret = models::euclidean_spin * ret; ret[2] = (r-1) * sqrt( pow(360/pconf.spiral_cone, 2) - 1); - models::apply_ball(ret[2], ret[1]); + ret = pconf.ball() * ret; } else { z = exp(z); @@ -2614,8 +2614,8 @@ EX void draw_model_elements() { ld z = acosh(tz); hyperpoint a = xpush0(z); - ld cb = models::cos_ball; - ld sb = models::sin_ball; + ld cb = pconf.ball() [1][1]; + ld sb = pconf.ball() [1][2]; a[1] = sb * a[2] / -cb; a[0] = sqrt(-1 + a[2] * a[2] - a[1] * a[1]); @@ -2807,11 +2807,13 @@ EX void draw_boundary(int w) { break; case mdHemisphere: { + ld cb = pconf.ball() [1][1]; + ld sb = pconf.ball() [2][1]; if(hyperbolic) { queuereset(mdPixel, p); for(int i=0; i<=360; i++) { ld s = sin(i * degree); - curvepoint(point3(current_display->radius * cos(i * degree), current_display->radius * s * (models::cos_ball * s >= 0 - 1e-6 ? 1 : abs(models::sin_ball)), 0)); + curvepoint(point3(current_display->radius * cos(i * degree), current_display->radius * s * (cb * s >= 0 - 1e-6 ? 1 : abs(sb)), 0)); } queuecurve(shiftless(Id), lc, fc, p); queuereset(pmodel, p); @@ -2820,7 +2822,7 @@ EX void draw_boundary(int w) { for(int i=0; i<=360; i++) { ld s = sin(i * degree); - curvepoint(point3(current_display->radius * cos(i * degree), current_display->radius * s * models::sin_ball, 0)); + curvepoint(point3(current_display->radius * cos(i * degree), current_display->radius * s * sb, 0)); } queuecurve(shiftless(Id), lc, fc, p); queuereset(pmodel, p); @@ -2842,8 +2844,8 @@ EX void draw_boundary(int w) { as_hyperboloid: ld& tz = pconf.top_z; ld mz = sphere ? atan(sqrt(tz*tz-1)) : acosh(tz); - ld cb = models::cos_ball; - ld sb = models::sin_ball; + ld cb = pconf.ball() [1][1]; + ld sb = pconf.ball() [2][1]; if(abs(sb) <= abs(cb) + 1e-5) { ld step = .01 / (1 << vid.linequality); @@ -3196,7 +3198,7 @@ EX int cone_side(const shiftpoint H) { ret[1] = cos(alpha) * r; ret[2] = (r-1) * sqrt( pow(360/pconf.spiral_cone, 2) - 1); - models::apply_ball(ret[2], ret[1]); + ret = pconf.ball() * ret; return ret; }; diff --git a/legacy.cpp b/legacy.cpp index 0ff24cb8..334e58b6 100644 --- a/legacy.cpp +++ b/legacy.cpp @@ -358,6 +358,11 @@ int read_legacy_args() { PHASE(3); start_game(); View = Id; playermoved = false; } + else if(argis("-ballangle")) { + PHASEFROM(2); + shift(); println(hlog, "-ballangle not implemented"); + // shift_arg_formula(vpconf.ballangle); + } else return 1; return 0; } diff --git a/models.cpp b/models.cpp index 25a6bc97..1904ab47 100644 --- a/models.cpp +++ b/models.cpp @@ -136,6 +136,8 @@ projection_configuration::projection_configuration() { dualfocus_autoscale = false; axial_angle = 90; ptr_model_orientation = new trans23; + ptr_ball = new transmatrix; + *ptr_ball = cspin(1, 2, 20._deg); } EX namespace models { @@ -144,7 +146,6 @@ EX namespace models { EX ld rotation_xz = 90; EX ld rotation_xy2 = 90; EX int do_rotate = 1; - EX ld cos_ball, sin_ball; EX bool model_straight, model_straight_yz; /** screen coordinates to orientation logical coordinates */ @@ -155,11 +156,6 @@ EX namespace models { EX void scr_to_ori(hyperpoint& h) { if(!model_straight) h = iso_inverse(pconf.mori().get()) * h; } EX void scr_to_ori(transmatrix& h) { if(!model_straight) h = iso_inverse(pconf.mori().get()) * h; } - #if HDR - template - void apply_ball(A& x, A& y) { tie(x,y) = make_pair(x*cos_ball + y*sin_ball, y*cos_ball - x*sin_ball); } - #endif - EX transmatrix rotmatrix() { if(GDIM == 2 || gproduct) return spin(rotation * degree); return spin(rotation_xy2 * degree) * cspin(0, 2, -rotation_xz * degree) * spin(rotation * degree); @@ -175,8 +171,6 @@ EX namespace models { EX transmatrix euclidean_spin; EX void configure() { - ld ball = -pconf.ballangle * degree; - cos_ball = cos(ball), sin_ball = sin(ball); model_straight = (pconf.mori().get()[0][0] > 1 - 1e-9); model_straight_yz = GDIM == 2 || (pconf.mori().get()[2][2] > 1-1e-9); if(history::on) history::apply(); @@ -603,7 +597,7 @@ EX namespace models { } if(is_3d(vpconf) && GDIM == 2 && !vr_settings) - add_edit(vpconf.ballangle); + add_edit(vpconf.ball()); if(vr_settings) { dialog::addSelItem(XLAT("VR: rotate the 3D model"), fts(vpconf.vr_angle) + "°", 'B'); @@ -848,10 +842,6 @@ EX namespace models { shift(); vpconf.formula = args(); } } - else if(argis("-ballangle")) { - PHASEFROM(2); - shift_arg_formula(vpconf.ballangle); - } else if(argis("-topz")) { PHASEFROM(2); shift_arg_formula(vpconf.top_z); @@ -1099,16 +1089,15 @@ EX namespace models { param_f(p.camera_angle, pp+"cameraangle", sp+"camera angle", 0); addsaver(p.ballproj, sp+"ballproj", 1); - param_f(p.ballangle, pp+"ballangle", sp+"ball angle", 20) - -> editable(0, 90, 5, "camera rotation in 3D models", + param_matrix(p.ball(), pp+"ballangle", 3) + -> editable("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 -- " "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.", - 'b') - -> unit = "°"; + 'b'); string help = "This parameter has a bit different scale depending on the settings:\n"