X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=examples%2Fboard_reprap%2Fsrc%2Freprap_gl.c;h=48e43ca23d28fc62454acb404027f58c3302d33b;hb=47a131708adafd4eba74038fd981baab91c1ff40;hp=a1fdd277b2b610a1129cd84ca5984d6d4610a025;hpb=561f3a68aa080ae9f53ea8cb5a1a0ed03ee04dbe;p=simavr diff --git a/examples/board_reprap/src/reprap_gl.c b/examples/board_reprap/src/reprap_gl.c index a1fdd27..48e43ca 100644 --- a/examples/board_reprap/src/reprap_gl.c +++ b/examples/board_reprap/src/reprap_gl.c @@ -20,9 +20,15 @@ */ #if __APPLE__ +#define GL_GLEXT_PROTOTYPES #include +#include +#include #else +#define GL_GLEXT_PROTOTYPES +#include #include +#include #endif #include @@ -31,17 +37,24 @@ #include "reprap.h" #include "reprap_gl.h" -#include "c3/c3.h" -#include "c3/c3camera.h" -#include "c3/c3arcball.h" -#include "c3/c3driver_context.h" -#include "c3/c3stl.h" +#include "c3.h" +#include "c3camera.h" +#include "c3driver_context.h" +#include "c3stl.h" +#include "c3lines.h" + +#include + +struct cairo_surface_t; int _w = 800, _h = 600; -c3cam cam; -c3arcball arcball; +//c3cam cam; c3context_p c3; +c3context_p hud; c3object_p head; +c3texture_p fbo_c3; + +int glsl_version = 110; extern reprap_t reprap; @@ -56,6 +69,208 @@ static int dumpError(const char * what) return count; } +#define GLCHECK(_w) {_w; dumpError(#_w);} + +void print_log(GLuint obj) +{ + int infologLength = 0; + int maxLength; + + if(glIsShader(obj)) + glGetShaderiv(obj,GL_INFO_LOG_LENGTH,&maxLength); + else + glGetProgramiv(obj,GL_INFO_LOG_LENGTH,&maxLength); + + char infoLog[maxLength]; + + if (glIsShader(obj)) + glGetShaderInfoLog(obj, maxLength, &infologLength, infoLog); + else + glGetProgramInfoLog(obj, maxLength, &infologLength, infoLog); + + if (infologLength > 0) + printf("%s\n",infoLog); +} +/* Global */ +GLuint fbo, fbo_texture, rbo_depth; +//GLuint vbo_fbo_vertices; + +static void +gl_offscreenInit( + int screen_width, + int screen_height) +{ + /* init_resources */ + /* Create back-buffer, used for post-processing */ + + /* Texture */ + GLCHECK(glActiveTexture(GL_TEXTURE0)); + glGenTextures(1, &fbo_texture); + glBindTexture(GL_TEXTURE_2D, fbo_texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, screen_width, screen_height, 0, + GL_RGBA, GL_UNSIGNED_BYTE, NULL); + glBindTexture(GL_TEXTURE_2D, 0); + + /* Depth buffer */ + GLCHECK(glGenRenderbuffers(1, &rbo_depth)); + glBindRenderbuffer(GL_RENDERBUFFER, rbo_depth); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, screen_width, + screen_height); + glBindRenderbuffer(GL_RENDERBUFFER, 0); + + /* Framebuffer to link everything together */ + GLCHECK(glGenFramebuffers(1, &fbo)); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, + fbo_texture, 0); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, + GL_RENDERBUFFER, rbo_depth); + + GLenum status; + if ((status = glCheckFramebufferStatus(GL_FRAMEBUFFER)) + != GL_FRAMEBUFFER_COMPLETE) { + fprintf(stderr, "glCheckFramebufferStatus: error %d", (int)status); + return ; + } +#if 0 + // Set the list of draw buffers. + GLenum DrawBuffers[2] = {GL_COLOR_ATTACHMENT0}; + glDrawBuffers(1, DrawBuffers); // "1" is the size of DrawBuffers + glBindFramebuffer(GL_FRAMEBUFFER, 0); +#endif +} + +void +gl_offscreenReshape( + int screen_width, + int screen_height) +{ +// Rescale FBO and RBO as well + glBindTexture(GL_TEXTURE_2D, fbo_texture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, screen_width, screen_height, 0, + GL_RGBA, GL_UNSIGNED_BYTE, NULL); + glBindTexture(GL_TEXTURE_2D, 0); + + glBindRenderbuffer(GL_RENDERBUFFER, rbo_depth); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, screen_width, + screen_height); + glBindRenderbuffer(GL_RENDERBUFFER, 0); + +// glBindFramebuffer(GL_FRAMEBUFFER, fbo); +// glViewport(0, 0, screen_width, screen_height); +// glBindFramebuffer(GL_FRAMEBUFFER, 0); +} + +void gl_offscreenFree() +{ + /* free_resources */ + glDeleteRenderbuffers(1, &rbo_depth); + glDeleteTextures(1, &fbo_texture); + glDeleteFramebuffers(1, &fbo); +// glDeleteBuffers(1, &vbo_fbo_vertices); +} + +GLuint program_postproc = 0, uniform_fbo_texture; + +static GLuint create_shader(const char * fname, GLuint pid) +{ + const GLchar * buf; + + FILE *f = fopen(fname, "r"); + if (!f) { + perror(fname); + return 0; + } + fseek(f, 0, SEEK_END); + long fs = ftell(f); + fseek(f, 0, SEEK_SET); + /* + * need to insert a header since there is nothing to detect the version number + * reliably without it, and __VERSION__ returns idiocy + */ + char head[128]; + sprintf(head, "#version %d\n#define GLSL_VERSION %d\n", glsl_version, glsl_version); + const int header = strlen(head); + buf = malloc(header + fs + 1); + memcpy((void*)buf, head, header); + fread((void*)buf + header, 1, fs, f); + ((char*)buf)[header + fs] = 0; + fclose(f); + + GLuint vs = glCreateShader(pid); + glShaderSource(vs, 1, &buf, NULL); + glCompileShader(vs); + dumpError("glCompileShader"); + print_log(vs); + free((void*)buf); + return vs; +} + + +int gl_ppProgram() +{ + int vs, fs; + int link_ok, validate_ok; + /* init_resources */ + /* Post-processing */ + if ((vs = create_shader("gfx/postproc.vs", GL_VERTEX_SHADER)) == 0) + return 0; + if ((fs = create_shader("gfx/postproc.fs", GL_FRAGMENT_SHADER)) == 0) + return 0; + + program_postproc = glCreateProgram(); + glAttachShader(program_postproc, vs); + glAttachShader(program_postproc, fs); + glLinkProgram(program_postproc); + glGetProgramiv(program_postproc, GL_LINK_STATUS, &link_ok); + if (!link_ok) { + fprintf(stderr, "glLinkProgram:"); + goto error; + } + glValidateProgram(program_postproc); + glGetProgramiv(program_postproc, GL_VALIDATE_STATUS, &validate_ok); + if (!validate_ok) { + fprintf(stderr, "glValidateProgram:"); + goto error; + } + + char * uniform_name = "m_Texture"; + uniform_fbo_texture = glGetUniformLocation(program_postproc, uniform_name); + if (uniform_fbo_texture == -1) { + fprintf(stderr, "Could not bind uniform %s\n", uniform_name); + goto error; + } + return 0; +error: + print_log(program_postproc); + glDeleteProgram(program_postproc); + program_postproc = 0; + return -1; +} + +void +gl_ppFree() +{ + if (program_postproc) + glDeleteProgram(program_postproc); + program_postproc = 0; +} + +static void +_gl_reshape_cb(int w, int h) +{ + _w = w; + _h = h; + + glViewport(0, 0, _w, _h); + gl_offscreenReshape(_w, _h); + glutPostRedisplay(); +} + static void _gl_key_cb( unsigned char key, @@ -76,50 +291,97 @@ _gl_key_cb( printf("Stopping VCD trace\n"); // avr_vcd_stop(&vcd_file); break; + case '1': + if (fbo_c3->geometry.mat.program.pid) + fbo_c3->geometry.mat.program.pid = 0; + else + fbo_c3->geometry.mat.program.pid = program_postproc; + glutPostRedisplay(); + break; + } +} + +static void +_c3_load_pixels( + c3pixels_p pix) +{ + GLuint mode = pix->normalize ? GL_TEXTURE_2D : GL_TEXTURE_RECTANGLE_ARB; + if (!pix->texture) { + printf("Creating texture %s %dx%d\n", pix->name ? pix->name->str : "", pix->w, pix->h); + pix->dirty = 1; + GLuint texID = 0; + dumpError("cp_gl_texture_load_argb flush"); + GLCHECK(glEnable(mode)); + + glGenTextures(1, &texID); +// glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, +// GL_MODULATE); //set texture environment parameters +// dumpError("glTexEnvf"); + + glPixelStorei(GL_UNPACK_ROW_LENGTH, pix->row / pix->psize); + glTexParameteri(mode, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + dumpError("GL_TEXTURE_MAG_FILTER");// + glTexParameteri(mode, GL_TEXTURE_MIN_FILTER, + pix->normalize ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR); + dumpError("GL_TEXTURE_MIN_FILTER"); + glTexParameteri(mode, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); + dumpError("GL_TEXTURE_WRAP_S"); + glTexParameteri(mode, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); + dumpError("GL_TEXTURE_WRAP_T"); + if (pix->normalize) + GLCHECK(glTexParameteri(mode, GL_GENERATE_MIPMAP, GL_TRUE)); + #if 1 + GLfloat fLargest; + glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &fLargest); + //printf("fLargest = %f\n", fLargest); + GLCHECK(glTexParameterf(mode, GL_TEXTURE_MAX_ANISOTROPY_EXT, fLargest)); + #endif + if (pix->normalize) + GLCHECK(glGenerateMipmap(mode)); + + pix->texture = texID; + pix->dirty = 1; + } + if (pix->dirty) { + pix->dirty = 0; + GLCHECK(glBindTexture(mode, pix->texture)); + glTexImage2D(mode, 0, + pix->format == C3PIXEL_A ? GL_ALPHA16 : GL_RGBA8, + pix->w, pix->h, 0, + pix->format == C3PIXEL_A ? GL_ALPHA : GL_BGRA, + GL_UNSIGNED_BYTE, + pix->base); + dumpError("glTexImage2D"); + if (pix->normalize) + GLCHECK(glGenerateMipmap(mode)); } } static void -_c3_geometry_prepare( +_c3_geometry_project( c3context_p c, - const struct c3driver_context_t *d, - c3geometry_p g) + const struct c3driver_context_t * d, + c3geometry_p g, + c3mat4p m) { + if (g->mat.texture) { +// printf("_c3_geometry_project xrure %d!\n", g->textures.count); + _c3_load_pixels(g->mat.texture); + } + switch(g->type.type) { - case C3_TRIANGLE_TYPE: { + case C3_TRIANGLE_TYPE: g->type.subtype = GL_TRIANGLES; - //g->mat.color = c3vec4f(0.0, 0.0, 1.0, 1.0); - } break; + break; case C3_TEXTURE_TYPE: { - c3texture_p t = (c3texture_p)g; - g->type.subtype = GL_TRIANGLE_FAN; - g->mat.color = c3vec4f(0.0, 1.0, 0.0, 0.5); - printf("_c3_geometry_prepare xrure %d!\n", g->textures.count); - if (!g->texture) { - GLuint texID = 0; - dumpError("cp_gl_texture_load_argb flush"); - - glEnable(GL_TEXTURE_RECTANGLE_ARB); - dumpError("cp_gl_texture_load_argb GL_TEXTURE_RECTANGLE_ARB"); - - glGenTextures(1, &texID); - dumpError("cp_gl_texture_load_argb glBindTexture GL_TEXTURE_RECTANGLE_ARB"); - - glPixelStorei(GL_UNPACK_ROW_LENGTH, t->pixels.row / 4); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - g->mat.texture = texID; - g->texture = 1; + // c3texture_p t = (c3texture_p)g; + if (g->mat.texture) { + g->type.subtype = GL_TRIANGLE_FAN; } - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, g->mat.texture); - glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, - t->pixels.w, t->pixels.h, 0, - GL_RGBA, GL_UNSIGNED_BYTE, - t->pixels.base); } break; + case C3_LINES_TYPE: + g->type.subtype = GL_TRIANGLES; + break; default: break; } @@ -132,35 +394,52 @@ _c3_geometry_draw( c3geometry_p g ) { glColor4fv(g->mat.color.n); + dumpError("glColor"); // glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, g->mat.color.n); glVertexPointer(3, GL_FLOAT, 0, g->projected.count ? g->projected.e : g->vertice.e); glEnableClientState(GL_VERTEX_ARRAY); - if (g->textures.count && g->texture) { - glDisable(GL_TEXTURE_2D); - glEnable(GL_TEXTURE_RECTANGLE_ARB); - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, g->mat.texture); - glTexCoordPointer(2, GL_FLOAT, 0, - g->textures.e); + dumpError("GL_VERTEX_ARRAY"); + glDisable(GL_TEXTURE_2D); + if (g->mat.texture) { + GLuint mode = g->mat.texture->normalize ? GL_TEXTURE_2D : GL_TEXTURE_RECTANGLE_ARB; + glEnable(mode); + if (g->mat.texture->trace) + printf("%s uses texture %s (%d tex)\n", + __func__, g->mat.texture->name->str, g->textures.count); + // printf("tex mode %d texture %d\n", g->mat.mode, g->mat.texture); + dumpError("glEnable texture"); + glBindTexture(mode, g->mat.texture->texture); + dumpError("glBindTexture"); + glTexCoordPointer(2, GL_FLOAT, 0, g->textures.e); glEnableClientState(GL_TEXTURE_COORD_ARRAY); - } else - glDisable(GL_TEXTURE_RECTANGLE_ARB); + dumpError("GL_TEXTURE_COORD_ARRAY"); + } + if (g->mat.program.pid) { + glUseProgram(g->mat.program.pid); + dumpError("glUseProgram program_postproc"); + } if (g->normals.count) { - glNormalPointer(GL_FLOAT, 0, - g->normals.e); + glNormalPointer(GL_FLOAT, 0, g->normals.e); glEnableClientState(GL_NORMAL_ARRAY); } - glDrawArrays(g->type.subtype, 0, g->vertice.count); + glDrawArrays(g->type.subtype, 0, + g->projected.count ? g->projected.count : g->vertice.count); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); + if (g->mat.texture) + glDisable(g->mat.texture->normalize ? GL_TEXTURE_2D : GL_TEXTURE_RECTANGLE_ARB); + if (g->mat.program.pid) + glUseProgram(0); } const c3driver_context_t c3context_driver = { - .geometry_prepare = _c3_geometry_prepare, + .geometry_project = _c3_geometry_project, .geometry_draw = _c3_geometry_draw, }; +float z_min, z_max; /* * Computes the distance from the eye, sort by this value */ @@ -175,9 +454,13 @@ _c3_z_sorter( c3vec3 c1 = c3vec3_add(g1->bbox.min, c3vec3_divf(c3vec3_sub(g1->bbox.max, g1->bbox.min), 2)); c3vec3 c2 = c3vec3_add(g2->bbox.min, c3vec3_divf(c3vec3_sub(g2->bbox.max, g2->bbox.min), 2)); - c3f d1 = c3vec3_length2(c3vec3_sub(c1, cam.eye)); - c3f d2 = c3vec3_length2(c3vec3_sub(c2, cam.eye)); + c3f d1 = c3vec3_length2(c3vec3_sub(c1, c3->cam.eye)); + c3f d2 = c3vec3_length2(c3vec3_sub(c2, c3->cam.eye)); + if (d1 > z_max) z_max = d1; + if (d1 < z_min) z_min = d1; + if (d2 > z_max) z_max = d2; + if (d2 < z_min) z_min = d2; /* * make sure transparent items are drawn after everyone else */ @@ -189,9 +472,51 @@ _c3_z_sorter( return d1 < d2 ? 1 : d1 > d2 ? -1 : 0; } +#define FBO 1 + static void _gl_display_cb(void) /* function called whenever redisplay needed */ { +#if FBO + /* + * Draw in FBO object + */ + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + // draw (without glutSwapBuffers) + dumpError("glBindFramebuffer fbo"); + glViewport(0, 0, _w, _h); + +#else + glBindFramebuffer(GL_FRAMEBUFFER, 0); +#endif + + c3vec3 headp = c3vec3f( + stepper_get_position_mm(&reprap.step_x), + stepper_get_position_mm(&reprap.step_y), + stepper_get_position_mm(&reprap.step_z)); + c3mat4 headmove = translation3D(headp); + c3transform_set(head->transform.e[0], &headmove); + + if (c3->root->dirty) { + // printf("reproject head %.2f,%.2f,%.2f\n", headp.x, headp.y,headp.z); + c3context_project(c3); + + z_min = 1000000000; + z_max = -1000000000; + qsort(c3->projected.e, c3->projected.count, sizeof(c3->projected.e[0]), + _c3_z_sorter); + z_min = sqrt(z_min); + z_max = sqrt(z_max); + // printf("z_min %f, z_max %f\n", z_min, z_max); + //z_min -= 50; + if (z_min < 0) + z_min = 10; + z_min = 10; + if (z_max < z_min || z_max > 1000) + z_max = 1000; + } + + glClearColor(1.0f, 1.0f, 1.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -199,65 +524,69 @@ _gl_display_cb(void) /* function called whenever redisplay needed */ glMatrixMode(GL_PROJECTION); // Select projection matrix glLoadIdentity(); // Start with an identity matrix - gluPerspective(60, _w / _h, 60, 400); - -// glDepthMask(GL_TRUE); -// glCullFace(GL_BACK); -// glEnable(GL_CULL_FACE); + gluPerspective(50, (float)_w / (float)_h, z_min, z_max); +#if 0 + glCullFace(GL_BACK); + glEnable(GL_CULL_FACE); +#endif + glDepthMask(GL_TRUE); + glDepthFunc(GL_LEQUAL); glEnable(GL_DEPTH_TEST); + glEnable(GL_LIGHTING); +// glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); - glEnable(GL_BLEND); // Enable Blending - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // Type Of Blending To Use - - glMatrixMode( GL_MODELVIEW ); - glLoadIdentity(); - // glMultMatrixf(arcball.rot.n); - glMultMatrixf(cam.mtx.n); - glTranslatef( -cam.eye.n[VX], -cam.eye.n[VY], -cam.eye.n[VZ] ); - // glMultMatrixf(arcball.rot.n); + glEnable(GL_ALPHA_TEST); + glAlphaFunc(GL_GREATER, 1.0f / 255.0f); + glEnable(GL_BLEND); // Enable Blending + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // Type Of Blending To Use - c3vec3 headp = c3vec3f( - stepper_get_position_mm(&reprap.step_x), - stepper_get_position_mm(&reprap.step_y), - stepper_get_position_mm(&reprap.step_z)); - c3mat4 headmove = translation3D(headp); - c3transform_set(head->transform.e[0], &headmove); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glMultMatrixf(c3->cam.mtx.n); + glTranslatef(-c3->cam.eye.n[VX], -c3->cam.eye.n[VY], -c3->cam.eye.n[VZ]); - if (c3->root->dirty) { - // printf("reproject\n"); - c3context_prepare(c3); + dumpError("flush"); - qsort(c3->projected.e, c3->projected.count, - sizeof(c3->projected.e[0]), _c3_z_sorter); - } c3context_draw(c3); +#if FBO + /* + * Draw back FBO over the screen + */ + glBindFramebuffer(GL_FRAMEBUFFER, 0); + dumpError("glBindFramebuffer 0"); + + glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); +#endif + glDisable(GL_DEPTH_TEST); + glDisable(GL_LIGHTING); + glDisable(GL_ALPHA_TEST); + + glUseProgram(0); + glMatrixMode(GL_PROJECTION); // Select projection matrix glLoadIdentity(); // Start with an identity matrix glOrtho(0, _w, 0, _h, 0, 10); - glScalef(1,-1,1); + glScalef(1, -1, 1); glTranslatef(0, -1 * _h, 0); - glMatrixMode(GL_MODELVIEW); // Select modelview matrix - - #if 0 - glPushMatrix(); glLoadIdentity(); // Start with an identity matrix - glScalef(3, 3, 1); - hd44780_gl_draw( - &hd44780, - colors[color][0], /* background */ - colors[color][1], /* character background */ - colors[color][2], /* text */ - colors[color][3] /* shadow */ ); - glPopMatrix(); -#endif + + if (hud) + c3context_draw(hud); + glutSwapBuffers(); } +#if !defined(GLUT_WHEEL_UP) +# define GLUT_WHEEL_UP 3 +# define GLUT_WHEEL_DOWN 4 +#endif + + int button; c3vec2 move; -c3cam startcam; static void _gl_button_cb( @@ -267,12 +596,22 @@ void _gl_button_cb( int y) { button = s == GLUT_DOWN ? b : 0; - startcam = cam; move = c3vec2f(x, y); - if (s == GLUT_DOWN) - c3arcball_mouse_down(&arcball, x, y); - else - c3arcball_mouse_up(&arcball); +// printf("button %d: %.1f,%.1f\n", b, move.x, move.y); + switch (b) { + case GLUT_LEFT_BUTTON: + case GLUT_RIGHT_BUTTON: // call motion + break; + case GLUT_WHEEL_UP: + case GLUT_WHEEL_DOWN: + if (c3->cam.distance > 10) { + const float d = 0.004; + c3cam_set_distance(&c3->cam, c3->cam.distance * ((b == GLUT_WHEEL_DOWN) ? (1.0+d) : (1.0-d))); + c3cam_update_matrix(&c3->cam); + c3->root->dirty = 1; // resort the array + } + break; + } } void @@ -283,26 +622,28 @@ _gl_motion_cb( c3vec2 m = c3vec2f(x, y); c3vec2 delta = c3vec2_sub(move, m); -// printf("%s b%d click %.1f,%.1f now %d,%d\n", -// __func__, button, move.n[0], move.n[1], x, y); +// printf("%s b%d click %.1f,%.1f now %d,%d delta %.1f,%.1f\n", +// __func__, button, move.n[0], move.n[1], x, y, delta.x, delta.y); switch (button) { case GLUT_LEFT_BUTTON: { - - // c3cam_eye_yaw(&cam, delta.n[0] / 4); - // c3cam_eye_pitch(&cam, delta.n[1] / 4); - - c3mat4 rotx = rotation3D(c3vec3f(1.0, 0, 0), delta.n[1] / 4); + c3mat4 rotx = rotation3D(c3->cam.side, delta.n[1] / 4); c3mat4 roty = rotation3D(c3vec3f(0.0, 0.0, 1.0), delta.n[0] / 4); rotx = c3mat4_mul(&rotx, &roty); - c3cam_rot_about_lookat(&cam, &rotx); + c3cam_rot_about_lookat(&c3->cam, &rotx); - c3cam_update_matrix(&cam); + c3cam_update_matrix(&c3->cam); c3->root->dirty = 1; // resort the array -// c3arcball_mouse_motion(&arcball, x, y, 0,0,0); } break; case GLUT_RIGHT_BUTTON: { + // offset both points, but following the plane + c3vec3 f = c3vec3_mulf(c3vec3f(-c3->cam.side.y, c3->cam.side.x, 0), -delta.n[1] / 4); + c3->cam.eye = c3vec3_add(c3->cam.eye, f); + c3->cam.lookat = c3vec3_add(c3->cam.lookat, f); + c3cam_movef(&c3->cam, delta.n[0] / 8, 0, 0); + c3cam_update_matrix(&c3->cam); + c3->root->dirty = 1; // resort the array } break; } move = m; @@ -313,9 +654,6 @@ static void _gl_timer_cb( int i) { - //static int oldstate = -1; - // restart timer - c3arcball_idle(&arcball); glutTimerFunc(1000 / 24, _gl_timer_cb, 0); glutPostRedisplay(); } @@ -327,7 +665,7 @@ gl_init( { glutInit(&argc, argv); /* initialize GLUT system */ - glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH); + glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH | GLUT_ALPHA); glutInitWindowSize(_w, _h); /* width=400pixels height=500pixels */ /*window =*/ glutCreateWindow("Press 'q' to quit"); /* create window */ @@ -337,23 +675,23 @@ gl_init( glutMouseFunc(_gl_button_cb); glutMotionFunc(_gl_motion_cb); + glutReshapeFunc(_gl_reshape_cb); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); + glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST); + /* glHint(GL_POINT_SMOOTH_HINT, GL_NICEST); glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST); - glEnable(GL_LINE_SMOOTH); - + */ // enable color tracking glEnable(GL_COLOR_MATERIAL); // set material properties which will be assigned by glColor glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE); - + /* setup some lights */ glShadeModel(GL_SMOOTH); -#if 1 -// glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); GLfloat global_ambient[] = { 0.5f, 0.5f, 0.5f, 1.0f }; glLightModelfv(GL_LIGHT_MODEL_AMBIENT, global_ambient); @@ -372,39 +710,138 @@ gl_init( glLightfv(GL_LIGHT0, GL_POSITION, position); glEnable(GL_LIGHT0); } -#endif -// glEnable(GL_BLEND); - // Works for the UI !! -// glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - cam = c3cam_new(); - cam.lookat = c3vec3f(100.0, 100.0, 0.0); - cam.eye = c3vec3f(100.0, -100.0, 100.0); - c3cam_update_matrix(&cam); + /* + * Extract the GLSL version as a nuneric value for later + */ + const char * glsl = (const char *)glGetString(GL_SHADING_LANGUAGE_VERSION); + { + int M = 0, m = 0; + if (sscanf(glsl, "%d.%d", &M, &m) == 2) + glsl_version = (M * 100) + m; + + } + printf("GL_SHADING_LANGUAGE_VERSION %s = %d\n", glsl, glsl_version); - c3arcball_init_center(&arcball, c3vec2f(_w/2, _h/2), 100); -// hd44780_gl_init(); + gl_offscreenInit(_w, _h); + gl_ppProgram(); c3 = c3context_new(_w, _h); static const c3driver_context_t * list[] = { &c3context_driver, NULL }; c3->driver = list; + c3->cam.lookat = c3vec3f(100.0, 100.0, 0.0); + c3->cam.eye = c3vec3f(100.0, -100.0, 100.0); + c3cam_update_matrix(&c3->cam); + + { + const char *path = "gfx/hb.png"; + cairo_surface_t * image = cairo_image_surface_create_from_png (path); + printf("image = %p %p\n", image, cairo_image_surface_get_data (image)); + c3texture_p b = c3texture_new(c3->root); + + c3pixels_p dst = c3pixels_new( + cairo_image_surface_get_width (image), + cairo_image_surface_get_height (image), + 4, cairo_image_surface_get_stride(image), + cairo_image_surface_get_data (image)); + dst->name = str_new(path); + b->geometry.mat.texture = dst; + b->size = c3vec2f(200, 200); + b->geometry.mat.color = c3vec4f(1.0, 1.0, 1.0, 1.0); +// c3transform_new(head); + } + c3pixels_p line_aa_tex = NULL; + { + const char *path = "gfx/BlurryCircle.png"; + cairo_surface_t * image = cairo_image_surface_create_from_png (path); + printf("image = %p %p\n", image, cairo_image_surface_get_data (image)); + +#if 0 + c3pixels_p dst = &b->pixels; + c3pixels_init(dst, + cairo_image_surface_get_width (image), + cairo_image_surface_get_height (image), + 1, cairo_image_surface_get_width (image), + NULL); + c3pixels_alloc(dst); + b->size = c3vec2f(32, 32); + b->normalized = 1; + + c3pixels_p src = c3pixels_new( + cairo_image_surface_get_width (image), + cairo_image_surface_get_height (image), + 4, cairo_image_surface_get_stride(image), + cairo_image_surface_get_data (image)); + + uint32_t * _s = (uint32_t *)src->base; + uint8_t * _d = (uint8_t *)dst->base; + int max = 0; + for (int i = 0; i < dst->h * dst->w; i++) + if ((_s[i] & 0xff) > max) + max = _s[i] & 0xff; + for (int i = 0; i < dst->h * dst->w; i++) + *_d++ = ((_s[i] & 0xff) * 255) / max;// + (0xff - max); + b->pixels.format = C3PIXEL_A; +#else + c3pixels_p dst = c3pixels_new( + cairo_image_surface_get_width (image), + cairo_image_surface_get_height (image), + 4, cairo_image_surface_get_stride(image), + cairo_image_surface_get_data (image)); + dst->format = C3PIXEL_ARGB; + dst->normalize = 1; + dst->name = str_new(path); + uint8_t * line = dst->base; + for (int y = 0; y < dst->h; y++, line += dst->row) { + uint32_t *p = (uint32_t *)line; + for (int x = 0; x < dst->w; x++, p++) { + uint8_t b = *p; + *p = ((0xff - b) << 24);//|(b << 16)|(b << 8)|(b); + } + } +#endif + line_aa_tex = dst; + + c3pixels_p p = dst; + printf("struct { int w, h, stride, size, format; uint8_t pix[] } img = {\n" + "%d, %d, %d, %d, %d\n", + p->w, p->h, (int)p->row, p->psize, cairo_image_surface_get_format(image)); + for (int i = 0; i < 32; i++) + printf("0x%08x ", ((uint32_t*)p->base)[i]); + printf("\n"); + } c3object_p grid = c3object_new(c3->root); { - for (int x = 0; x < 20; x++) { - for (int y = 0; y < 20; y++) { + for (int x = 0; x <= 20; x++) { + for (int y = 0; y <= 20; y++) { c3vec3 p[4] = { - c3vec3f(-1+x*10,y*10,0), c3vec3f(1+x*10,y*10,0), - c3vec3f(x*10,-1+y*10,0), c3vec3f(x*10,1+y*10,0), + c3vec3f(-1+x*10,y*10,0.01), c3vec3f(1+x*10,y*10,0.01), + c3vec3f(x*10,-1+y*10,0.02), c3vec3f(x*10,1+y*10,0.02), }; c3geometry_p g = c3geometry_new( - c3geometry_type(C3_RAW_TYPE, GL_LINES), grid); - g->mat.color = c3vec4f(0.0, 0.0, 0.0, 1.0); - c3vertex_array_insert(&g->vertice, - g->vertice.count, p, 4); + c3geometry_type(C3_LINES_TYPE, 0), grid); + g->mat.color = c3vec4f(0.0, 0.0, 0.0, 0.8); + g->mat.texture = line_aa_tex; + c3lines_init(g, p, 4, 0.2); } } } + + if (0) { + c3vec3 p[4] = { + c3vec3f(-5,-5,1), c3vec3f(205,-5,1), + }; + c3geometry_p g = c3geometry_new( + c3geometry_type(C3_LINES_TYPE, 0), grid); + g->mat.color = c3vec4f(0.0, 0.0, 0.0, 1.0); + g->mat.texture = line_aa_tex; + g->line.width = 2; + + c3vertex_array_insert(&g->vertice, + g->vertice.count, p, 2); + + } head = c3stl_load("gfx/buserror-nozzle-model.stl", c3->root); //head = c3object_new(c3->root); c3transform_new(head); @@ -419,6 +856,38 @@ gl_init( memset(b->pixels.base, 0xff, 10 * b->pixels.row); #endif + + hud = c3context_new(_w, _h); + hud->driver = list; + /* + * This is the offscreen framebuffer where the 3D scene is drawn + */ + if (FBO) { + c3texture_p b = c3texture_new(hud->root); + + c3pixels_p dst = c3pixels_new(_w, _h, 4, _w * 4, NULL); + dst->name = str_new("fbo"); + dst->texture = fbo_texture; + dst->normalize = 1; + dst->dirty = 0; + // dst->trace = 1; + b->geometry.mat.texture = dst; + b->geometry.mat.program.pid = program_postproc; + b->size = c3vec2f(_w, _h); + b->geometry.mat.color = c3vec4f(1.0, 1.0, 1.0, 1.0); + fbo_c3 = b; + } + + { + c3vec3 p[4] = { + c3vec3f(10,10,0), c3vec3f(800-10,10,0), + }; + c3geometry_p g = c3geometry_new( + c3geometry_type(C3_LINES_TYPE, 0), hud->root); + g->mat.color = c3vec4f(0.5, 0.5, 1.0, .3f); + g->mat.texture = line_aa_tex; + c3lines_init(g, p, 2, 10); + } return 1; }