ray:: horospherical hyperbolic honeycombs

This commit is contained in:
Zeno Rogue 2019-11-02 10:40:22 +01:00
parent bde53b5c78
commit 272c628229
4 changed files with 117 additions and 11 deletions

View File

@ -558,6 +558,21 @@ EX namespace binary {
return S7-1;
}
EX int dirs_outer() {
switch(geometry) {
case gBinary3: return 4;
case gHoroTris: return 4;
case gHoroRec: return 2;
case gHoroHex: return 6;
default: return -1;
}
}
EX int dirs_inner() {
if(among(geometry, gBinaryTiling, gHoroHex)) return 2;
return 1;
}
EX void build_tmatrix() {
if(among(geometry, gBinaryTiling, gSol)) return; // unused
use_direct = (1 << (S7-1)) - 1;

View File

@ -586,6 +586,19 @@ EX transmatrix parabolic13(ld u, ld v) {
}
}
EX hyperpoint parabolic10(hyperpoint h) {
if(euclid) { h[MDIM] = 1; return h; }
else if(MDIM == 4) return hyperpoint(sinh(h[0]), h[1]/exp(h[0]), h[2]/exp(h[0]), cosh(h[0]));
else return hyperpoint(sinh(h[0]), h[1]/exp(h[0]), cosh(h[0]), 0);
}
EX hyperpoint deparabolic10(const hyperpoint h) {
if(euclid) return h;
ld x = -log(h[LDIM] - h[0]);
if(MDIM == 3) return hyperpoint(x, h[1] * exp(x), 1, 0);
return point31(x, h[1] * exp(x), h[2] * exp(x));
}
EX transmatrix spintoc(const hyperpoint& H, int t, int f) {
transmatrix T = Id;
ld R = hypot(H[f], H[t]);

View File

@ -709,6 +709,11 @@ void geometry_information::compute_cornerbonus() { }
hyperpoint ray_kleinize(hyperpoint h, int id, ld pz) {
if(geometry == gNil && among(id, 2, 5)) h[2] = 0;
if(hyperbolic && binarytiling) {
// ld co = vid.binary_width / log(2) / 4;
// hyperpoint res = point31(h[2]*log(2)/2, h[0]*co, h[1]*co);
return deparabolic10(binary::parabolic3(h[0], h[1]) * xpush0(log(2)/2*h[2]));
}
if(prod) {
return point3(h[0]/h[2], h[1]/h[2], pz);
}
@ -918,7 +923,7 @@ void geometry_information::create_wall3d() {
ld h = binary::horohex_scale / 2;
hyperpoint down = point3(0,0,2*z);
for(int i=0; i<3; i++) {
for(int j=0; j<4; j++) for(int i=0; i<3; i++) {
transmatrix T = cspin(0, 1, 2*M_PI*i/3);
hyperpoint hcenter = point3(0,0,-z);
@ -929,10 +934,10 @@ void geometry_information::create_wall3d() {
hyperpoint hcn = T*point3(-h*2,0, -z);
hyperpoint hun = T*point3(-h*3,+r3,-z);
hyperpoint hdn = T*point3(-h*3,-r3,-z);
make_wall(i, {hcenter, hu0, hu1, hd1, hd0});
make_wall(i+3, {hcn, hun, hdn});
make_wall(i+6, make4(hd1, hu1, hd1+down));
make_wall(i+9, make4(hun, hdn, hun+down));
if(j == 0) make_wall(i, {hcenter, hu0, hu1, hd1, hd0});
if(j == 1) make_wall(i+3, {hcn, hun, hdn});
if(j == 2) make_wall(i+6, make4(hd1, hu1, hd1+down));
if(j == 3) make_wall(i+9, make4(hun, hdn, hun+down));
}
make_wall(12, {point3(3*h,r3,z), point3(0,2*r3,z), point3(-3*h,r3,z)});

View File

@ -54,7 +54,7 @@ eGeometry last_geometry;
/** is the raycaster available? */
EX bool available() {
if(WDIM == 2) return false;
if(hyperbolic && pmodel == mdPerspective && !binarytiling)
if(hyperbolic && pmodel == mdPerspective && !penrose)
return true;
if((sol || nil) && pmodel == mdGeodesic)
return true;
@ -79,6 +79,7 @@ struct raycaster : glhr::GLprogram {
GLint tConnections, tWallcolor, tTextureMap;
GLint uBinaryWidth, uPLevel, uLP;
GLint uLinearSightRange, uExpStart, uExpDecay;
GLint uBLevel;
raycaster(string vsh, string fsh) : GLprogram(vsh, fsh) {
println(hlog, "assigning");
@ -101,6 +102,8 @@ struct raycaster : glhr::GLprogram {
uLinearSightRange = glGetUniformLocation(_program, "uLinearSightRange");
uExpDecay = glGetUniformLocation(_program, "uExpDecay");
uExpStart = glGetUniformLocation(_program, "uExpStart");
uBLevel = glGetUniformLocation(_program, "uBLevel");
tConnections = glGetUniformLocation(_program, "tConnections");
tWallcolor = glGetUniformLocation(_program, "tWallcolor");
@ -158,14 +161,24 @@ void enable_raycaster() {
"uniform float uPLevel;\n"
"uniform mat4 uLP;\n";
if(IN_ODS) fsh +=
int flat1 = 0, flat2 = S7;
if(hyperbolic && binarytiling) {
fsh += "uniform float uBLevel;\n";
flat1 = binary::dirs_outer();
flat2 -= binary::dirs_inner();
}
if(IN_ODS || hyperbolic) fsh +=
"mat4 xpush(float x) { return mat4("
"cosh(x), 0., 0., sinh(x),\n"
"0., 1., 0., 0.,\n"
"0., 0., 1., 0.,\n"
"sinh(x), 0., 0., cosh(x)"
");}\n"
");}\n";
if(IN_ODS) fsh +=
"mat4 xzspin(float x) { return mat4("
"cos(x), 0., sin(x), 0.,\n"
@ -184,6 +197,9 @@ void enable_raycaster() {
fsh +=
"vec2 map_texture(vec4 pos, int which) {\n";
if(nil) fsh += "if(which == 2 || which == 5) pos.z = 0.;\n";
else if(hyperbolic && binarytiling) fsh +=
"pos = vec4(-log(pos.w-pos.x), pos.y, pos.z, 1);\n"
"pos.yz *= exp(pos.x);\n";
else if(hyperbolic) fsh +=
"pos /= pos.w;\n";
else if(prod) fsh +=
@ -269,7 +285,7 @@ void enable_raycaster() {
fmain +=
" if(which == -1) {\n";
fmain += "for(int i=0; i<"+its(S7)+"; i++) {\n";
fmain += "for(int i="+its(flat1)+"; i<"+its(flat2)+"; i++) {\n";
if(in_h2xe()) fmain +=
" float v = ((position - uM[i] * position)[2] / (uM[i] * tangent - tangent)[2]);\n"
@ -301,6 +317,31 @@ void enable_raycaster() {
fmain +=
" if(d < dist) { dist = d; which = i; }\n"
"}\n";
// 20: get to horosphere +uBLevel (take smaller root)
// 21: get to horosphere -uBLevel (take larger root)
if(hyperbolic && binarytiling) {
fmain +=
"for(int i=20; i<22; i++) {\n"
"float sgn = i == 20 ? -1. : 1.;\n"
"vec4 zpos = xpush(uBLevel*sgn) * position;\n"
"vec4 ztan = xpush(uBLevel*sgn) * tangent;\n"
"float Mp = zpos.w - zpos.x;\n"
"float Mt = ztan.w - ztan.x;\n"
"float a = (Mp*Mp-Mt*Mt);\n"
"float b = Mp/a;\n"
"float c = (1.+Mt*Mt) / a;\n"
"if(b*b < c) continue;\n"
"if(sgn < 0. && Mt > 0.) continue;\n"
"float zsgn = (Mt > 0. ? -sgn : sgn);\n"
"float u = sqrt(b*b-c)*zsgn + b;\n"
"float v = -(Mp*u-1.) / Mt;\n"
"float d = asinh(v);\n"
"if(d < 0. && abs(log(position.w*position.w-position.x*position.x)) < uBLevel) continue;\n"
"if(d < dist) { dist = d; which = i; }\n"
"}\n";
}
if(prod) fmain +=
"if(zspeed > 0.) { float d = (uPLevel - zpos) / zspeed; if(d < dist) { dist = d; which = "+its(S7)+"+1; }}\n"
@ -461,10 +502,29 @@ void enable_raycaster() {
else fmain +=
"position = position + tangent * dist;\n";
if(hyperbolic && binarytiling) {
fmain +=
"if(which == 20) {\n"
" float best = 999.;\n"
" for(int i="+its(flat2)+"; i<"+its(S7)+"; i++) {\n"
" float cand = len(uM[i] * position);\n"
" if(cand < best) { best = cand; which = i; }\n"
" }\n"
"}\n"
"if(which == 21) {\n"
"float best = 999.;\n"
"for(int i=0; i<"+its(flat1)+"; i++) {\n"
" float cand = len(uM[i] * position);\n"
" if(cand < best) { best = cand; which = i; }\n"
" }\n"
// "gl_FragColor = vec4(.5 + .5 * sin((go+dist)*100.), 1, float(which)/3., 1); return;\n"
"}\n";
}
fmain += " go = go + dist;\n";
fmain += "if(which == -1) continue;\n";
if(prod) fmain += "position.w = -zpos;\n";
// apply wall color
@ -525,6 +585,17 @@ void enable_raycaster() {
if(use_reflect) {
if(prod) fmain += "if(reflect && which >= "+its(S7)+") { zspeed = -zspeed; continue; }\n";
if(hyperbolic && binarytiling) fmain +=
"if(reflect && (which < "+its(flat1)+" || which >= "+its(flat2)+")) {\n"
" float x = -log(position.w - position.x);\n"
" vec4 xtan = xpush(-x) * tangent;\n"
" float diag = (position.y*position.y+position.z*position.z)/2.;\n"
" vec4 normal = vec4(1.-diag, -position.y, -position.z, -diag);\n"
" float mdot = dot(xtan.xyz, normal.xyz) - xtan.w * normal.w;\n"
" xtan = xtan - normal * mdot * 2.;\n"
" tangent = xpush(x) * xtan;\n"
" continue;\n"
" }\n";
if(sol) fmain +=
" if(reflect) {\n"
" if(which == 0 || which == 4) tangent.x = -tangent.x;\n"
@ -765,6 +836,8 @@ EX void cast() {
glUniform1f(o->uBinaryWidth, vid.binary_width * log(2) / 2);
if(o->uPLevel != -1)
glUniform1f(o->uPLevel, cgi.plevel / 2);
if(o->uBLevel != -1)
glUniform1f(o->uBLevel, log(binary::expansion()) / 2);
glUniform1f(o->uLinearSightRange, sightranges[geometry]);
glUniform1f(o->uExpDecay, exp_decay_current());