From: Mikko Rasa Date: Sat, 12 Dec 2015 14:37:53 +0000 (+0200) Subject: Implement vertical keystone and cylinder corrections X-Git-Url: http://git.tdb.fi/?a=commitdiff_plain;h=77803dd85ecfa2cc3c7265f8f64c535064181eed;p=geometrycompositor.git Implement vertical keystone and cylinder corrections There's no configuration interface yet. --- diff --git a/Makefile b/Makefile index aa04a2b..5f0dc21 100644 --- a/Makefile +++ b/Makefile @@ -1,2 +1,2 @@ geometrycompositor: source/main.c - gcc -o $@ $< -Wall -Wextra -Werror -std=c90 -pedantic -ggdb -lX11 -lXcomposite -lXdamage -lXext -lXrandr -lGL + gcc -o $@ $< -Wall -Wextra -Werror -std=c90 -pedantic -ggdb -lm -lX11 -lXcomposite -lXdamage -lXext -lXrandr -lGL diff --git a/source/main.c b/source/main.c index 13038c2..4beab4b 100644 --- a/source/main.c +++ b/source/main.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -33,6 +34,10 @@ typedef struct CompositedMonitor int y; unsigned width; unsigned height; + float keystone_vertical; + float cylinder_depth; + float vertical_center; + float perspective; unsigned vertex_buffer; unsigned index_buffer; unsigned vertex_array; @@ -455,24 +460,49 @@ void update_monitor_vertices(CompositedScreen *screen, CompositedMonitor *monito unsigned short *index_data; unsigned x, y; unsigned i; + float aspect; + float cyl_w_sq; + float sin_ksv; + float cos_ksv; t = monitor->tessellation; data_size = (t+1)*(t+1)*4*sizeof(float); vertex_data = (float *)malloc(data_size); + aspect = (float)monitor->width/monitor->height; + cyl_w_sq = 0.25f-(0.5f-monitor->cylinder_depth)*(0.5f-monitor->cylinder_depth); + sin_ksv = monitor->keystone_vertical/sqrt(1.0f+monitor->keystone_vertical*monitor->keystone_vertical); + cos_ksv = sqrt(1.0f-sin_ksv*sin_ksv); for(y=0; y<=t; ++y) for(x=0; x<=t; ++x) { - float xf, yf; + float xf, yf, z, rz; + float scale; float *v; xf = (float)x/t; yf = (float)y/t; + v = vertex_data+(y*(t+1)+x)*4; - v[0] = xf; - v[1] = yf; v[2] = (monitor->x+xf*monitor->width)/screen->width; v[3] = (monitor->y+yf*monitor->height)/screen->height; + + z = sqrt(0.25f-(xf-0.5f)*(xf-0.5f)*4.0f*cyl_w_sq)-0.5f+monitor->cylinder_depth; + if(monitor->keystone_vertical>0) + { + rz = (1.0f-yf)/aspect*sin_ksv+z*cos_ksv; + yf = 1.0f-((1.0f-yf)*cos_ksv-z*aspect*sin_ksv); + z = rz; + } + else if(monitor->keystone_vertical<0) + { + rz = z*cos_ksv-yf/aspect*sin_ksv; + yf = yf*cos_ksv+z*aspect*sin_ksv; + z = rz; + } + scale = monitor->perspective/(monitor->perspective+z); + v[0] = 0.5f+(xf-0.5f)*scale; + v[1] = monitor->vertical_center+(yf-monitor->vertical_center)*scale; } glBindBuffer(GL_ARRAY_BUFFER, monitor->vertex_buffer); glBufferData(GL_ARRAY_BUFFER, data_size, vertex_data, GL_STATIC_DRAW); @@ -522,11 +552,16 @@ int initialize_monitor(Compositor *compositor, CompositedScreen *screen, Composi XRRFreeCrtcInfo(crtc); XRRFreeOutputInfo(output); + monitor->keystone_vertical = 0.0f; + monitor->cylinder_depth = 0.0f; + monitor->vertical_center = 0.5f; + monitor->perspective = 1.0f; + glGenBuffers(2, buffers); monitor->vertex_buffer = buffers[0]; monitor->index_buffer = buffers[1]; - monitor->tessellation = 20; + monitor->tessellation = 50; update_monitor_vertices(screen, monitor); stride = 4*sizeof(float);