From d1f9b38df9dbe416341869c1bd630fe24367673e Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Mon, 14 Dec 2015 23:02:22 +0200 Subject: [PATCH] Implement a spherical curvature correction --- source/control.c | 59 ++++++++++++++++++++++++++++++------------------ source/main.c | 47 ++++++++++++++++++++++++++++---------- 2 files changed, 72 insertions(+), 34 deletions(-) diff --git a/source/control.c b/source/control.c index fc0f871..292c108 100644 --- a/source/control.c +++ b/source/control.c @@ -11,7 +11,8 @@ typedef struct GeometryCorrection { char *monitor_name; float keystone_vertical; - float cylinder_depth; + int curvature_type; + float curvature_depth; float vertical_center; float perspective; } GeometryCorrection; @@ -141,8 +142,8 @@ GeometryCorrection *get_corrections(Display *display) for(i=0; ivalues_length) - ncorrections = values_length/4; + if(ncorrections*5>values_length) + ncorrections = values_length/5; corrections = (GeometryCorrection *)malloc((ncorrections+1)*sizeof(GeometryCorrection)); name_ptr = names; @@ -154,10 +155,11 @@ GeometryCorrection *get_corrections(Display *display) corrections[i].monitor_name = (char *)malloc(namelen+1); strcpy(corrections[i].monitor_name, name_ptr); - corrections[i].keystone_vertical = values[i*4]/4096.0f; - corrections[i].cylinder_depth = values[i*4+1]/4096.0f; - corrections[i].vertical_center = values[i*4+2]/4096.0f; - corrections[i].perspective = values[i*4+3]/4096.0f; + corrections[i].keystone_vertical = values[i*5]/4096.0f; + corrections[i].curvature_type = values[i*5+1]; + corrections[i].curvature_depth = values[i*5+2]/4096.0f; + corrections[i].vertical_center = values[i*5+3]/4096.0f; + corrections[i].perspective = values[i*5+4]/4096.0f; name_ptr += namelen+1; } @@ -191,24 +193,25 @@ void set_corrections(Display *display, GeometryCorrection *corrections) } names = (char *)malloc(total_len+ncorrections); - values = (short *)malloc(ncorrections*4*sizeof(short)); + values = (short *)malloc(ncorrections*5*sizeof(short)); name_ptr = names; for(i=0; ikeystone_vertical -= 1.0f/64; else if(keysym==XK_w) - target->cylinder_depth += 1.0f/256; + target->curvature_depth += 1.0f/256; else if(keysym==XK_s) - target->cylinder_depth -= 1.0f/256; + target->curvature_depth -= 1.0f/256; else if(keysym==XK_e) target->vertical_center += 1.0f/32; else if(keysym==XK_d) @@ -410,6 +413,8 @@ int interactive(Display *display, GeometryCorrection *corrections, GeometryCorre target->perspective += 1.0f/16; else if(keysym==XK_f) target->perspective -= 1.0f/16; + else if(keysym==XK_z) + target->curvature_type = target->curvature_type%2+1; else break; @@ -447,9 +452,9 @@ int main(int argc, char **argv) GeometryCorrection *corrections; unsigned i; - if(argc!=2 && argc!=6) + if(argc!=2 && argc!=7) { - fprintf(stderr, "Usage: %s [ ]\n", argv[0]); + fprintf(stderr, "Usage: %s [ ]\n", argv[0]); return 1; } @@ -475,19 +480,29 @@ int main(int argc, char **argv) strcpy(corrections[i].monitor_name, argv[1]); corrections[i+1].monitor_name = NULL; corrections[i].keystone_vertical = 0.0f; - corrections[i].cylinder_depth = 0.0f; + corrections[i].curvature_type = 1; + corrections[i].curvature_depth = 0.0f; corrections[i].vertical_center = 0.5f; corrections[i].perspective = 1.0f; } if(argc==2) interactive(display, corrections, &corrections[i]); - else if(argc==6) + else if(argc==7) { + if(!strcmp(argv[3], "cylindrical")) + corrections[i].curvature_type = 1; + else if(!strcmp(argv[3], "spherical")) + corrections[i].curvature_type = 2; + else + { + fprintf(stderr, "Invalid curvature\n"); + return 1; + } corrections[i].keystone_vertical = strtod(argv[2], NULL); - corrections[i].cylinder_depth = strtod(argv[3], NULL); - corrections[i].vertical_center = strtod(argv[4], NULL); - corrections[i].perspective = strtod(argv[5], NULL); + corrections[i].curvature_depth = strtod(argv[4], NULL); + corrections[i].vertical_center = strtod(argv[5], NULL); + corrections[i].perspective = strtod(argv[6], NULL); set_corrections(display, corrections); } diff --git a/source/main.c b/source/main.c index 024e849..b1247d8 100644 --- a/source/main.c +++ b/source/main.c @@ -32,6 +32,12 @@ typedef struct CompositedWindow int recreate_mask; } CompositedWindow; +enum +{ + CYLINDRICAL = 1, + SPHERICAL +}; + typedef struct CompositedMonitor { char *name; @@ -41,7 +47,8 @@ typedef struct CompositedMonitor unsigned width; unsigned height; float keystone_vertical; - float cylinder_depth; + float curvature_type; + float curvature_depth; float vertical_center; float perspective; unsigned vertex_buffer; @@ -611,9 +618,9 @@ void update_monitor_vertices(CompositedScreen *screen, CompositedMonitor *monito aspect = (float)monitor->width/monitor->height; - if(monitor->cylinder_depth) + if(monitor->curvature_depth) { - cyl_radius = (monitor->cylinder_depth*monitor->cylinder_depth+0.25f)/(2.0f*monitor->cylinder_depth); + cyl_radius = (monitor->curvature_depth*monitor->curvature_depth+0.25f)/(2.0f*monitor->curvature_depth); cyl_arc = 2.0f*asin(0.5f/cyl_radius); } @@ -638,10 +645,24 @@ void update_monitor_vertices(CompositedScreen *screen, CompositedMonitor *monito v[0] = (float)x/t-0.5f; v[1] = ((float)y/t-0.5f)/aspect; v[2] = 0; - if(monitor->cylinder_depth) + if(monitor->curvature_depth) { - v[2] = (1.0f-cos(v[0]*cyl_arc))*cyl_radius-monitor->cylinder_depth; - v[0] = sin(v[0]*cyl_arc)*cyl_radius; + if(monitor->curvature_type==CYLINDRICAL) + { + v[2] = (1.0f-cos(v[0]*cyl_arc))*cyl_radius-monitor->curvature_depth; + v[0] = sin(v[0]*cyl_arc)*cyl_radius; + } + else if(monitor->curvature_type==SPHERICAL) + { + float r; + + v[0] = tan(v[0]*cyl_arc)*cyl_radius; + v[1] = tan(v[1]*cyl_arc)*cyl_radius; + r = sqrt(v[0]*v[0]+v[1]*v[1]+cyl_radius*cyl_radius)/fabs(cyl_radius); + v[0] /= r; + v[1] /= r; + v[2] = cyl_radius-cyl_radius/r-monitor->curvature_depth; + } } } @@ -736,7 +757,8 @@ int initialize_monitor(Compositor *compositor, CompositedScreen *screen, XRRScre XRRFreeOutputInfo(output); monitor->keystone_vertical = 0.0f; - monitor->cylinder_depth = 0.0f; + monitor->curvature_type = CYLINDRICAL; + monitor->curvature_depth = 0.0f; monitor->vertical_center = 0.5f; monitor->perspective = 1.0f; @@ -821,7 +843,7 @@ void update_geometry_correction(Compositor *compositor, CompositedScreen *screen use_gl(compositor, screen); name_ptr = names; - for(i=0; i*4+3keystone_vertical = values[i*4]/4096.0f; - monitor->cylinder_depth = values[i*4+1]/4096.0f; - monitor->vertical_center = values[i*4+2]/4096.0f; - monitor->perspective = values[i*4+3]/4096.0f; + monitor->keystone_vertical = values[i*5]/4096.0f; + monitor->curvature_type = values[i*5+1]; + monitor->curvature_depth = values[i*5+2]/4096.0f; + monitor->vertical_center = values[i*5+3]/4096.0f; + monitor->perspective = values[i*5+4]/4096.0f; if(monitor->enabled) update_monitor_vertices(screen, monitor); -- 2.43.0