]> git.tdb.fi Git - geometrycompositor.git/commitdiff
Implement a spherical curvature correction
authorMikko Rasa <tdb@tdb.fi>
Mon, 14 Dec 2015 21:02:22 +0000 (23:02 +0200)
committerMikko Rasa <tdb@tdb.fi>
Mon, 14 Dec 2015 21:02:22 +0000 (23:02 +0200)
source/control.c
source/main.c

index fc0f8718c4e554e92dd41f8505b1f8598478d2a5..292c108bc34538a9399ded9b7672df58fdd1df0e 100644 (file)
@@ -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; i<names_length; ++i)
                if(!names[i])
                        ++ncorrections;
-       if(ncorrections*4>values_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; i<ncorrections; ++i)
        {
                strcpy(name_ptr, corrections[i].monitor_name);
                name_ptr += strlen(name_ptr)+1;
 
-               values[i*4] = corrections[i].keystone_vertical*4096;
-               values[i*4+1] = corrections[i].cylinder_depth*4096;
-               values[i*4+2] = corrections[i].vertical_center*4096;
-               values[i*4+3] = corrections[i].perspective*4096;
+               values[i*5] = corrections[i].keystone_vertical*4096;
+               values[i*5+1] = corrections[i].curvature_type;
+               values[i*5+2] = corrections[i].curvature_depth*4096;
+               values[i*5+3] = corrections[i].vertical_center*4096;
+               values[i*5+4] = corrections[i].perspective*4096;
        }
 
        root = DefaultRootWindow(display);
        monitors_atom = XInternAtom(display, "_MSP_GEOMETRY_CORRECTION_MONITORS", False);
        correction_atom = XInternAtom(display, "_MSP_GEOMETRY_CORRECTION", False);
        XChangeProperty(display, root, monitors_atom, XA_STRING, 8, PropModeReplace, (unsigned char *)names, total_len+ncorrections-1);
-       XChangeProperty(display, root, correction_atom, XA_INTEGER, 16, PropModeReplace, (unsigned char *)values, ncorrections*4);
+       XChangeProperty(display, root, correction_atom, XA_INTEGER, 16, PropModeReplace, (unsigned char *)values, ncorrections*5);
 
        free(names);
        free(values);
@@ -399,9 +402,9 @@ int interactive(Display *display, GeometryCorrection *corrections, GeometryCorre
                        else if(keysym==XK_a)
                                target->keystone_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 <monitor> [<keystone> <cylinder> <vcenter> <perspective>]\n", argv[0]);
+               fprintf(stderr, "Usage: %s <monitor> [<keystone> <curvature> <depth> <vcenter> <perspective>]\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);
        }
index 024e84930d88209f58cc0dcdbe9b643015b959a4..b1247d88d680ec012d36215fc0bede6fcb8f782b 100644 (file)
@@ -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+3<values_length; ++i)
+       for(i=0; i*5+4<values_length; ++i)
        {
                CompositedMonitor *monitor;
 
@@ -831,10 +853,11 @@ void update_geometry_correction(Compositor *compositor, CompositedScreen *screen
                monitor = find_monitor_by_name(screen, name_ptr);
                if(monitor)
                {
-                       monitor->keystone_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);