/* * GTK code: * Copyright (C) 1998 Janne Löf * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * VDF parser: * Courtesy of Dr. Robert Geist, Clemson University, Clemson, SC. */ #include #include #include #include #include #include #include #include #include #include "serial.h" #include "fob.h" #include "main.h" void texture_init(int i) { /* param i is the "name", which is Stephen's index+1, because index 0 is special for this glBindTextureEXT() */ FILE *fopen(), *fptr; char buf[512]; char *parse; int max_color; int im_size, im_width, im_height; unsigned char *texture_bytes; /* load a ppm file */ fptr = fopen(texfilenames[i-1],"r"); fgets(buf,512,fptr); do { fgets(buf,512,fptr); } while(buf[0] == '#'); parse = strtok(buf," "); im_width = atoi(parse); parse = strtok(NULL,"\n"); im_height = atoi(parse); fgets(buf,512,fptr); parse = strtok(buf," "); max_color = atoi(parse); im_size = im_width*im_height; texture_bytes = (unsigned char *)calloc(3,im_size); fread(texture_bytes,1,3*im_size,fptr); fclose(fptr); /* this is a speed-up; drawing then just uses re_bind */ glBindTextureEXT(GL_TEXTURE_2D,i); /* declare this to be the current texture */ glPixelStorei(GL_UNPACK_ALIGNMENT,1); glTexImage2D(GL_TEXTURE_2D,0,3,im_width,im_height,0, GL_RGB,GL_UNSIGNED_BYTE,texture_bytes); glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE); cfree(texture_bytes); } void glint_init(char *gdfname) { FILE *fopen(), *fptr; int i,j,k; int patches,gridsize; int width, length; char dstring[80]; char c; fptr = fopen(gdfname,"r"); /* read light spec. description, but have to save it for the compiled list, so that all possible transformations apply on every new gluLookAt */ fscanf(fptr,"%s",dstring); /* begin_lighting */ fscanf(fptr,"%s",dstring); /* begin_light */ fscanf(fptr,"%s",dstring); /* light_position */ for(i=0;i<3;i++) fscanf(fptr,"%f",&(light0_position[i])); light0_position[3] = 1.0; fscanf(fptr,"%s",dstring); /* light_specular */ for(i=0;i<3;i++) fscanf(fptr,"%f",&(light0_specular[i])); light0_specular[3] = 1.0; fscanf(fptr,"%s",dstring); /* end_light */ fscanf(fptr,"%s",dstring); /* end_lighting */ glNewList(ICO_LIST_GLINT,GL_COMPILE); glShadeModel(GL_SMOOTH); glPolygonMode(GL_FRONT,GL_FILL); glPolygonMode(GL_BACK,GL_FILL); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); glEnable(GL_BLEND); glBlendFunc(GL_ONE,GL_ONE); /* turn off scene default ambient */ glLightModelfv(GL_LIGHT_MODEL_AMBIENT,light0_ambient); glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER,1); glLightfv(GL_LIGHT0,GL_AMBIENT,light0_ambient); glLightfv(GL_LIGHT0,GL_DIFFUSE,light0_diffuse); glLightfv(GL_LIGHT0,GL_SPECULAR,light0_specular); glLightfv(GL_LIGHT0,GL_POSITION,light0_position); glLightf(GL_LIGHT0,GL_SPOT_CUTOFF,90.0); glLightf(GL_LIGHT0,GL_CONSTANT_ATTENUATION,1.0); glLightf(GL_LIGHT0,GL_LINEAR_ATTENUATION,0.0); glLightf(GL_LIGHT0,GL_QUADRATIC_ATTENUATION,0.0); glEnable(GL_LIGHT0); fscanf(fptr,"%s",dstring); /* begin geometry */ fscanf(fptr,"%s",dstring); /* begin mesh */ while(strncmp(dstring,"end_geometry",strlen("end_geometry")) != 0) { fscanf(fptr,"%s",dstring); /* dimension */ fscanf(fptr,"%d %d",&width,&length); gridsize = width * length; fscanf(fptr,"%s",dstring); /* mat_shininess */ fscanf(fptr,"%f",&mat_shininess[1]); fscanf(fptr,"%s",dstring); /* mat_specular */ for(i=0;i<3;i++) fscanf(fptr,"%f",&mat_specular[i]); mat_specular[3]=1.0; glMaterialfv(GL_FRONT,GL_AMBIENT,mat_ambient); glMaterialfv(GL_FRONT,GL_DIFFUSE,mat_diffuse); glMaterialfv(GL_FRONT,GL_SPECULAR,mat_specular); glMaterialfv(GL_FRONT,GL_SHININESS,mat_shininess); fscanf(fptr,"%s",dstring); /* begin vertices */ vertices = (struct point *)calloc(gridsize,sizeof(struct point)); for(i=0;icount > 0) return TRUE; gtk_widget_grab_focus(GTK_WIDGET(glarea)); /* OpenGL calls can be done only if begingl returns true */ /* old if (gtk_gl_area_begingl(GTK_GL_AREA(glarea))) { */ if (gtk_gl_area_make_current(GTK_GL_AREA(glarea))) { /* clear entire GL area */ glDrawBuffer(GL_BACK); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glPushMatrix(); /* left viewport */ // glViewport(0, 0, 1280, 1024); // glViewport(0, 0, 640, 480); glViewport(0, 0, 1280, 480); /* draw */ draw(); glPopMatrix(); /* opengl rendering done for now */ /* old - not needed anymore gtk_gl_area_endgl(GTK_GL_AREA(glarea)); */ } /* swap backbuffer to front */ gtk_gl_area_swapbuffers(GTK_GL_AREA(glarea)); return TRUE; } gint glarea_configure(GtkWidget *widget, GdkEventConfigure *event) { /* OpenGL calls can be done only if begingl returns true */ if (gtk_gl_area_begingl(GTK_GL_AREA(widget))) { /* glViewport(0,0, widget->allocation.width, widget->allocation.height); */ /* end opengl calls by calling endgl */ gtk_gl_area_endgl(GTK_GL_AREA(widget)); } return TRUE; } gint glarea_motion_notify(GtkWidget *widget, GdkEventMotion *event) { gint x, y; GdkRectangle area; GdkModifierType state; if (event->is_hint) { gdk_window_get_pointer(event->window, &x, &y, &state); } else { x = (gint)event->x; y = (gint)event->y; state = (GdkModifierType)event->state; } area.x = 0; area.y = 0; area.width = widget->allocation.width; area.height = widget->allocation.height; if(state & GDK_BUTTON1_MASK) { /* ... Drag in progress, simulate trackball ... */ /* DEBUG g_print("Mouse motion button 1 at coordinates (%d,%d)\n",x,y); */ } if(state & GDK_BUTTON2_MASK) { /* ... Zooming drag ... */ /* DEBUG g_print("Mouse motion button 2 at coordinates (%d,%d)\n",x,y); */ } if(state & GDK_BUTTON3_MASK) { /* ... 3rd button drag ... */ g_print("Mouse motion button 3 at coordinates (%d,%d)\n",x,y); } /* ... scene (orientation, zoom) has changed, redraw ... */ gtk_widget_draw(widget, (GdkRectangle *)NULL); return(TRUE); } gint glarea_button_press(GtkWidget *widget, GdkEventButton *event) { gint return_status=TRUE; /* note: set return_status=FALSE if doing further processing like pop-up menu */ switch(event->type) { case GDK_BUTTON_PRESS: switch(event->button) { case 1: case 2: case 3: default: g_print("Mouse button %d click at coordinates (%lf,%lf)\n", event->button,event->x,event->y); break; } break; case GDK_2BUTTON_PRESS: switch(event->button) { case 1: case 2: case 3: default: g_print("Mouse button %d double-click at coordinates (%lf,%lf)\n", event->button,event->x,event->y); break; } break; case GDK_3BUTTON_PRESS: g_print("Mouse button %d triple-click at coordinates (%lf,%lf)\n", event->button,event->x,event->y); break; default: g_print("Unknown button press event\n"); return_status=FALSE; break; } return(return_status); } gint key_press_event(GtkWidget *widget, GdkEventKey *event) { switch (event->keyval) { case GDK_r: break; case GDK_l: break; case GDK_p: break; case GDK_g: break; case GDK_a: break; case GDK_f: break; case GDK_u: break; case GDK_b: break; case GDK_m: break; case GDK_n: break; case GDK_q: main_quit(); break; } gtk_widget_draw(glarea, (GdkRectangle *)NULL); return (TRUE); } gint popup_menu_handler(GtkWidget *widget, GdkEventButton *event) { if (event->button == 3) { gtk_menu_popup(GTK_MENU(widget), NULL, NULL, NULL, NULL, event->button, event->time); return TRUE; } return FALSE; } void popup_menu_detacher(GtkWidget *attach_widget,GtkMenu *menu) { } gint create_window() { /* create new top level window */ window = gtk_window_new( GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(window), "GCV"); gtk_window_set_position(GTK_WINDOW(window),GTK_WIN_POS_MOUSE); gtk_container_border_width(GTK_CONTAINER(window), 5); gtk_signal_connect(GTK_OBJECT(window), "key_press_event", GTK_SIGNAL_FUNC(key_press_event), NULL); gtk_signal_connect (GTK_OBJECT(window), "delete_event", GTK_SIGNAL_FUNC(main_quit), NULL); /* destroy this window when exiting from gtk_main() */ gtk_quit_add_destroy(1, GTK_OBJECT(window)); /* create new OpenGL widget with GTK's window mode; analogous to glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH); mode(GL_DOUBLE | GL_RGBA | GL_DEPTH); */ glarea = gtk_gl_area_new_vargs(NULL, /* no sharing */ GDK_GL_DOUBLEBUFFER, GDK_GL_RGBA, GDK_GL_DEPTH_SIZE,1, GDK_GL_NONE); /* last argument must be GDK_GL_NONE */ if (glarea == NULL) { g_print("Can't create GtkGLArea widget\n"); return FALSE; } /* set up events and signals for OpenGL widget */ gtk_widget_set_events(GTK_WIDGET(glarea), GDK_EXPOSURE_MASK| GDK_BUTTON_PRESS_MASK| GDK_BUTTON_RELEASE_MASK| GDK_KEY_PRESS_MASK| GDK_KEY_RELEASE_MASK| GDK_POINTER_MOTION_MASK| GDK_POINTER_MOTION_HINT_MASK); gtk_signal_connect (GTK_OBJECT(glarea), "expose_event", GTK_SIGNAL_FUNC(glarea_expose), NULL); gtk_signal_connect(GTK_OBJECT(glarea), "motion_notify_event", GTK_SIGNAL_FUNC(glarea_motion_notify), NULL); gtk_signal_connect (GTK_OBJECT(glarea), "button_press_event", GTK_SIGNAL_FUNC(glarea_button_press), NULL); gtk_signal_connect (GTK_OBJECT(glarea), "configure_event", GTK_SIGNAL_FUNC(glarea_configure), NULL); /* gtk_signal_connect (GTK_OBJECT(glarea), "key_press_event", GTK_SIGNAL_FUNC(key_press_event), NULL); */ gtk_signal_connect (GTK_OBJECT(glarea), "delete_event", GTK_SIGNAL_FUNC(main_quit), NULL); //gtk_widget_set_usize(GTK_WIDGET(glarea), 1280, 1024); /* minimum size */ //gtk_widget_set_usize(GTK_WIDGET(glarea), 640, 480); /* minimum size */ gtk_widget_set_usize(GTK_WIDGET(glarea), 1280, 480); /* minimum size */ gtk_quit_add_destroy(1, GTK_OBJECT(glarea)); /* put glarea into window and show it all */ gtk_container_add(GTK_CONTAINER(window),GTK_WIDGET(glarea)); gtk_widget_show(glarea); gtk_widget_show(window); /* set focus to glarea widget */ /* needed? GTK_WIDGET_SET_FLAGS(glarea, GTK_CAN_FOCUS); gtk_widget_grab_focus(GTK_WIDGET(glarea)); */ /* moved to main glinit(); */ return TRUE; } int main(int argc, char **argv) { int i; int num_events; int birds=2; char vdf_file[100]; char gdf_file[100]; /* initialize gtk */ gtk_init(&argc,&argv); /* Check if OpenGL (GLX extension) is supported. */ if (gdk_gl_query() == FALSE) { g_print("OpenGL not supported\n"); return(0); } create_window(); if(argc==3) { fprintf(stderr,"glints on\n"); strcpy(gdf_file,argv[2]); glint_init(gdf_file); glints = 1; } else if(argc==2) { fprintf(stderr,"no glints\n"); strcpy(vdf_file,argv[1]); glinit(vdf_file); } else { fprintf(stderr,"Usage: %s \n",argv[0]); exit(0); } if((fob = fob_make("/dev/ttyS0",birds))==NULL) { fprintf(stderr,"can't allocate fob\n"); exit(1); } fprintf(stderr,"fob open\n"); if(!fob_open(fob)) { fprintf(stderr,"can't open fob\n"); exit(1); } fprintf(stderr,"fob start\n"); fob_start(fob,POSITION_MATRIX); gtk_idle_add(main_loop,NULL); gtk_main(); return(0); } void main_quit() { fob_stop(fob); gtk_main_quit(); } static gint main_loop(gpointer data) { int i; /* get FOB data */ fob_getposmatdata(fob); eye[0] = -fob->p[HEAD][1]; eye[1] = -fob->p[HEAD][2]; eye[2] = fob->p[HEAD][0]; dir[0] = -fob->m[HEAD][M2A(0,1,4,4)]; dir[1] = -fob->m[HEAD][M2A(0,2,4,4)]; dir[2] = fob->m[HEAD][M2A(0,0,4,4)]; upv[0] = fob->m[HEAD][M2A(2,1,4,4)]; upv[1] = fob->m[HEAD][M2A(2,2,4,4)]; upv[2] = -fob->m[HEAD][M2A(2,0,4,4)]; /* DEBUG ------- (checking arbitrary matrix mult by FOB matrix) ------ */ /* fprintf(stderr,"dir BEFORE: (%6.2f, %6.2f, %6.2f)\n",dir[0],dir[1],dir[2]); */ /* Does multiplying by FOB matrix work? Try multiplying (0,0,-1) first... YES! It does work! the dir vector, obtained by multiplying (0,0,-1) thru by the FOB matrix and then negating the z-coordinate generates the exact same dir vector as the above three lines */ /* mid[0] = 0.0; mid[1] = 0.0; mid[2] = -1.0; dir[0] = mid[0] * fob->m[HEAD][M2A(1,1,4,4)] + mid[1] * fob->m[HEAD][M2A(2,1,4,4)] + mid[2] * fob->m[HEAD][M2A(0,1,4,4)]; dir[1] = mid[0] * fob->m[HEAD][M2A(1,2,4,4)] + mid[1] * fob->m[HEAD][M2A(2,2,4,4)] + mid[2] * fob->m[HEAD][M2A(0,2,4,4)]; dir[2] = mid[0] * fob->m[HEAD][M2A(1,0,4,4)] + mid[1] * fob->m[HEAD][M2A(2,0,4,4)] + mid[2] * fob->m[HEAD][M2A(0,0,4,4)]; dir[2] = -1.0 * dir[2]; */ /* DEBUG fprintf(stderr,"dir AFTER: (%6.2f, %6.2f, %6.2f)\n",dir[0],dir[1],dir[2]); */ /* DEBUG ------------------------------------------------------------- */ for(i=0;i<3;i++) ref[i] = eye[i] + d * dir[i]; gtk_widget_draw(glarea,(GdkRectangle *)NULL); }