X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fcontrol.c;h=292c108bc34538a9399ded9b7672df58fdd1df0e;hb=d1f9b38df9dbe416341869c1bd630fe24367673e;hp=f0c3357fc8018fb74ba33f4445597b6fa57f3a5a;hpb=326681cd9c807e5be2fc9fd8e13d3026b7ec39a8;p=geometrycompositor.git diff --git a/source/control.c b/source/control.c index f0c3357..292c108 100644 --- a/source/control.c +++ b/source/control.c @@ -1,18 +1,109 @@ +#define GL_GLEXT_PROTOTYPES #include #include #include #include #include +#include +#include typedef struct GeometryCorrection { char *monitor_name; float keystone_vertical; - float cylinder_depth; + int curvature_type; + float curvature_depth; float vertical_center; float perspective; } GeometryCorrection; +typedef struct InteractiveView +{ + Window window; + GLXContext glx_context; + GLXWindow glx_window; + Atom geometry_data_atom; + unsigned shaders[5]; + unsigned programs[2]; + unsigned buffers[2]; + unsigned nelements; +} InteractiveView; + +static unsigned short frustum_indices[] = { 2, 1, 3, 0, 1, 0xFFFF, 3, 4, 2, 0, 4, 0xFFFF }; +static float view_matrix[] = +{ + 0.70711f, 0.40825f, -0.57735f, 0.0f, + 0.0f, 0.81650f, 0.57735f, 0.0f, + 0.70711f, -0.40725f, 0.57735f, 0.0f, + -0.2f, 0.0f, -2.5f, 1.0f +}; +static float projection_matrix[] = +{ + 2.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 2.6667f, 0.0f, 0.0f, + 0.0f, 0.0f, -1.1f, -1.0f, + 0.0f, 0.0f, -1.05f, 0.0f +}; + +static const char *vshader_src = + "#version 150\n" + "uniform mat4 view;\n" + "in vec4 vertex;\n" + "void main()\n" + "{\n" + " gl_Position = view*vertex;\n" + "}\n"; + +static const char *gshader_src = + "#version 150\n" + "layout(triangles) in;\n" + "layout(triangle_strip, max_vertices=3) out;\n" + "uniform mat4 projection;\n" + "out vec3 normal;\n" + "void main()\n" + "{\n" + " vec3 v0 = gl_in[0].gl_Position.xyz;\n" + " vec3 v1 = gl_in[1].gl_Position.xyz;\n" + " vec3 v2 = gl_in[2].gl_Position.xyz;\n" + " vec3 tri_normal = normalize(cross(v1-v0, v2-v0));\n" + " for(int i=0; i<3; ++i)\n" + " {\n" + " normal = tri_normal;\n" + " gl_Position = projection*gl_in[i].gl_Position;\n" + " EmitVertex();\n" + " }\n" + " EndPrimitive();\n" + "}\n"; + +static const char *fshader_src = + "#version 150\n" + "in vec3 normal;\n" + "out vec4 frag_color;\n" + "void main()\n" + "{\n" + " frag_color = vec4(vec3(0.5+clamp(normal.z, 0.0, 1.0)*0.5), 1.0);\n" + "}\n"; + +static const char *flat_vshader_src = + "#version 150\n" + "uniform mat4 view;\n" + "uniform mat4 projection;\n" + "in vec4 vertex;\n" + "void main()\n" + "{\n" + " gl_Position = projection*view*vertex;\n" + "}\n"; + +static const char *flat_fshader_src = + "#version 150\n" + "uniform vec4 color;\n" + "out vec4 frag_color;\n" + "void main()\n" + "{\n" + " frag_color = color;\n" + "}\n"; + + GeometryCorrection *get_corrections(Display *display) { Window root; @@ -51,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; @@ -64,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]/10000.0f; - corrections[i].cylinder_depth = values[i*4+1]/10000.0f; - corrections[i].vertical_center = values[i*4+2]/10000.0f; - corrections[i].perspective = values[i*4+3]/10000.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; } @@ -101,38 +193,268 @@ 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; ivisual, AllocNone); + view->window = XCreateWindow(display, root, 0, 0, 1024, 768, 0, vi->depth, InputOutput, vi->visual, CWColormap, &win_attr); + XStoreName(display, view->window, "Geometry correction control"); + XMapWindow(display, view->window); + + view->glx_window = glXCreateWindow(display, configs[0], view->window, NULL); + view->glx_context = glXCreateNewContext(display, configs[0], GLX_RGBA_TYPE, NULL, True); + glXMakeContextCurrent(display, view->glx_window, view->glx_window, view->glx_context); + + XFree(configs); + XFree(vi); + + view->shaders[0] = create_shader(GL_VERTEX_SHADER, vshader_src); + view->shaders[1] = create_shader(GL_GEOMETRY_SHADER, gshader_src); + view->shaders[2] = create_shader(GL_FRAGMENT_SHADER, fshader_src); + view->programs[0] = create_program(view->shaders, 3); + view->shaders[3] = create_shader(GL_VERTEX_SHADER, flat_vshader_src); + view->shaders[4] = create_shader(GL_FRAGMENT_SHADER, flat_fshader_src); + view->programs[1] = create_program(view->shaders+3, 2); + glUniform4f(glGetUniformLocation(view->programs[1], "color"), 0.0f, 0.6f, 1.0f, 1.0f); + + glGenBuffers(2, view->buffers); + glBindBuffer(GL_ARRAY_BUFFER, view->buffers[0]); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(float), NULL); + glEnableVertexAttribArray(0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, view->buffers[1]); + + glEnable(GL_PRIMITIVE_RESTART); + glPrimitiveRestartIndex(0xFFFF); + + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LEQUAL); + + view->geometry_data_atom = XInternAtom(display, "_MSP_GEOMETRY_CORRECTION_DATA", False); + XSelectInput(display, view->window, KeyPressMask|ExposureMask); + + return 1; +} + +void request_geometry_data(Display *display, InteractiveView *view, GeometryCorrection *target) +{ + XChangeProperty(display, view->window, view->geometry_data_atom, XA_STRING, 8, PropModeReplace, (unsigned char *)target->monitor_name, strlen(target->monitor_name)); + XConvertSelection(display, view->geometry_data_atom, view->geometry_data_atom, view->geometry_data_atom, view->window, CurrentTime); +} + +void update_view(Display *display, InteractiveView *view, XSelectionEvent *event) +{ + Atom prop_type; + int prop_format; + unsigned long overflow; + unsigned long data_length; + short *geometry_data; + unsigned tessellation; + unsigned nvertices; + float *vertex_data; + unsigned nindices; + unsigned short *index_data; + unsigned i; + int x, y; + + XGetWindowProperty(display, event->requestor, event->property, 0, 32262, False, XA_INTEGER, + &prop_type, &prop_format, &data_length, &overflow, (unsigned char **)&geometry_data); + + tessellation = geometry_data[0]; + nvertices = 5+(tessellation+1)*(tessellation+1); + + vertex_data = (float *)malloc(nvertices*3*sizeof(float)); + for(i=0; inelements = tessellation*((tessellation+1)*2+1)-1; + + nindices = 12+view->nelements; + index_data = (unsigned short *)malloc(nindices*sizeof(unsigned short)); + memcpy(index_data, frustum_indices, sizeof(frustum_indices)); + i = 12; + for(y=0; y<(int)tessellation; ++y) + { + if(y>0) + index_data[i++] = 0xFFFF; + for(x=0; x<=(int)tessellation; ++x) + { + index_data[i++] = 5+(y+1)*(tessellation+1)+x; + index_data[i++] = 5+y*(tessellation+1)+x; + } + } + + glBufferData(GL_ARRAY_BUFFER, nvertices*3*sizeof(float), vertex_data, GL_STATIC_DRAW); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, nindices*sizeof(unsigned short), index_data, GL_STATIC_DRAW); + + free(vertex_data); + free(index_data); + XFree(geometry_data); +} + +int interactive(Display *display, GeometryCorrection *corrections, GeometryCorrection *target) +{ + InteractiveView view; + int update_pending; + int done; + + initialize_view(display, &view); + request_geometry_data(display, &view, target); + + done = 0; + update_pending = 0; + while(!done) + { + XEvent event; + KeySym keysym; + + XNextEvent(display, &event); + + switch(event.type) + { + case KeyPress: + keysym = XLookupKeysym(&event.xkey, 0); + if(keysym==XK_Escape) + { + done = 1; + break; + } + else if(update_pending) + break; + else if(keysym==XK_q) + target->keystone_vertical += 1.0f/64; + else if(keysym==XK_a) + target->keystone_vertical -= 1.0f/64; + else if(keysym==XK_w) + target->curvature_depth += 1.0f/256; + else if(keysym==XK_s) + target->curvature_depth -= 1.0f/256; + else if(keysym==XK_e) + target->vertical_center += 1.0f/32; + else if(keysym==XK_d) + target->vertical_center -= 1.0f/32; + else if(keysym==XK_r) + 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; + + set_corrections(display, corrections); + request_geometry_data(display, &view, target); + update_pending = 1; + + break; + case SelectionNotify: + if(event.xselection.property==view.geometry_data_atom) + { + update_view(display, &view, &event.xselection); + update_pending = 0; + } + break; + default: + printf("event %d\n", event.type); + break; + } + + glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); + glUseProgram(view.programs[0]); + glDrawElements(GL_TRIANGLE_STRIP, view.nelements, GL_UNSIGNED_SHORT, (void *)(12*sizeof(unsigned short))); + glUseProgram(view.programs[1]); + glDrawElements(GL_LINE_STRIP, 11, GL_UNSIGNED_SHORT, NULL); + glXSwapBuffers(display, view.glx_window); + } + + return 0; +} + int main(int argc, char **argv) { Display *display; GeometryCorrection *corrections; unsigned i; - if(argc!=6) + if(argc!=2 && argc!=7) { - fprintf(stderr, "Usage: %s \n", argv[0]); + fprintf(stderr, "Usage: %s [ ]\n", argv[0]); return 1; } @@ -157,16 +479,38 @@ int main(int argc, char **argv) corrections[i].monitor_name = (char *)malloc(namelen+1); strcpy(corrections[i].monitor_name, argv[1]); corrections[i+1].monitor_name = NULL; + corrections[i].keystone_vertical = 0.0f; + corrections[i].curvature_type = 1; + corrections[i].curvature_depth = 0.0f; + corrections[i].vertical_center = 0.5f; + corrections[i].perspective = 1.0f; } - 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); + if(argc==2) + interactive(display, corrections, &corrections[i]); + 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].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); + set_corrections(display, corrections); + } XCloseDisplay(display); + for(i=0; corrections[i].monitor_name; ++i) + free(corrections[i].monitor_name); + free(corrections); return 0; }