#include #include #include #include #include #include #include #include #include #include #include #include #include #include "final1.h" #include "final2.h" /* Globals */ GtkWidget *glarea = NULL; /* global lights */ GLfloat white_light [] = {LIGHT_SCALE_INIT, LIGHT_SCALE_INIT, LIGHT_SCALE_INIT, 1.0}; GLfloat amb_light [] = {AMB_LIGHT_SCALE_INIT, AMB_LIGHT_SCALE_INIT, AMB_LIGHT_SCALE_INIT, 1.0}; /* global colors */ float color [4] = {COLOR_R_INIT, COLOR_G_INIT, COLOR_B_INIT, 1.0}; float amb_color [4] = {AMB_COLOR_R_INIT, AMB_COLOR_R_INIT, AMB_COLOR_R_INIT, 1.0}; /* global lookat position */ float lookat [3] = {LOOKAT_X_INIT, LOOKAT_Y_INIT, LOOKAT_Z_INIT}; /* global adjustment scales */ GtkAdjustment *light_scale; GtkAdjustment *ambient_scale; GtkAdjustment *red_scale; GtkAdjustment *green_scale; GtkAdjustment *blue_scale; GtkAdjustment *rotation_scale; /* global material properties */ GLfloat mat_specular [] = {1.0, 0.0, 0.0, 0.0}; GLfloat mat_shininess [] = {10.0}; void initgl (void) { /* initialize opengl stuff */ /* ... Specify clear color (black) ... */ glClearColor(0.0,0.0,0.0,0.0); /* ... Turn on depth testing (z-buffering) ... */ glEnable(GL_DEPTH_TEST); glClearDepth(1.0); /* ... Turn on blending (for transparency) ... */ glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); } gint glarea_expose(GtkWidget *widget, GdkEventExpose *event) { /* handle an expose event -- that is, redraw window when it's exposed after being covered up by another window */ /* ... Draw only last expose ... */ if(event->count > 0) { return TRUE; } redraw (); return TRUE; } gint glarea_configure(GtkWidget *widget, GdkEventConfigure *event) { /* configure the window where we'll be drawing the sphere */ /* ... 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; } GtkWidget *create_gl_window () { /* create the window where we'll be drawing the sphere */ GtkWidget *glwindow; /* ... Create the window which will hold glarea ... */ /* ... Create a window in gtk - note the window is NOT visible yet ... */ glwindow = gtk_window_new(GTK_WINDOW_TOPLEVEL); /* ... Set window attributes ... */ gtk_window_set_title(GTK_WINDOW(glwindow), "Scene"); gtk_container_border_width(GTK_CONTAINER(glwindow), 5); gtk_signal_connect (GTK_OBJECT(glwindow), "delete_event", GTK_SIGNAL_FUNC(gtk_main_quit), NULL); /* ... Destroy this window when exiting from gtk_main() ... */ gtk_quit_add_destroy(1, GTK_OBJECT(glwindow)); /* ... Create new OpenGL widget with GTK's window mode; analogous to glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_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 arg must be GDK_GL_NONE */ if (!glarea) { 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), "configure_event", GTK_SIGNAL_FUNC(glarea_configure), NULL); gtk_signal_connect (GTK_OBJECT(glarea), "delete_event", GTK_SIGNAL_FUNC(gtk_main_quit), NULL); gtk_widget_set_usize(glarea, 640, 480); /* minimum size */ gtk_quit_add_destroy(1, GTK_OBJECT(glarea)); /* ... Insert glarea into window and show it all ... */ gtk_container_add(GTK_CONTAINER(glwindow),glarea); gtk_widget_show(glarea); gtk_widget_show(glwindow); /* ... Set focus to glarea widget and initialize OpenGL ... */ GTK_WIDGET_SET_FLAGS(glarea,GTK_CAN_FOCUS); gtk_widget_grab_focus(GTK_WIDGET(glarea)); initgl(); return(glwindow); } GtkWidget *create_ctl_window () { /* create the GTK window with the controls */ GtkWidget *ctlwindow; /* ... Create the control window ... */ /* ... Create a window in gtk - note the window is NOT visible yet ... */ ctlwindow = gtk_window_new(GTK_WINDOW_TOPLEVEL); /* ... Call destroyapp when the window gets a "delete_event" signal ... */ gtk_signal_connect(GTK_OBJECT(ctlwindow),"delete_event", GTK_SIGNAL_FUNC(destroyapp), NULL); /* ... Put some breathing room around objects in the container ... */ gtk_container_border_width(GTK_CONTAINER(ctlwindow),15); /* ... Add controls to window ... */ add_controls (ctlwindow); /* ... Now, make the window visible ... */ gtk_widget_show(ctlwindow); return(ctlwindow); } void add_controls (GtkWidget *parent_window) { /* add the controls (sliders, buttons, etc.) to the GTK window */ /* control window widgets */ GtkWidget *rotation; GtkWidget *light_intensity; GtkWidget *ambient_intensity; GtkWidget *red_intensity; GtkWidget *green_intensity; GtkWidget *blue_intensity; GtkWidget *reset_button; GtkWidget *quit_button; /* formatting widgets */ GtkWidget *box1, *box2, *box3; GtkWidget *label; /* format widget init -- done only once */ box1 = gtk_vbox_new (FALSE, 0); gtk_container_add (GTK_CONTAINER (parent_window), box1); gtk_widget_show (box1); /* Camera label */ box2 = gtk_hbox_new (FALSE, 20); gtk_container_set_border_width (GTK_CONTAINER (box2), 10); gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0); gtk_widget_show (box2); label = gtk_label_new ("Camera:"); gtk_misc_set_alignment (GTK_MISC (label), 0, 0); gtk_box_pack_start (GTK_BOX (box2), label, FALSE, FALSE, 0); gtk_widget_show (label); /* camera rotate scale */ box2 = gtk_hbox_new (FALSE, 20); gtk_container_set_border_width (GTK_CONTAINER (box2), 10); gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0); gtk_widget_show (box2); label = gtk_label_new (" Camera Rotation:"); gtk_misc_set_alignment (GTK_MISC (label), 0, 0); gtk_box_pack_start (GTK_BOX (box2), label, FALSE, FALSE, 0); gtk_widget_show (label); /* for creating a new adjustment, you need the following 6 parameters: initial scale value, lowest scale value, highest scale value, increment, and two other which will always be 0.2 and 0.0 */ rotation_scale = (GtkAdjustment *)gtk_adjustment_new (0.0, 0.0, 360.0, 1.0, 0.2, 0.0); rotation = gtk_hscale_new (rotation_scale); gtk_widget_set_usize (GTK_WIDGET (rotation), 200, 30); gtk_box_pack_start (GTK_BOX (box2), rotation, TRUE, TRUE, 0); /* call the function rotation_change whenever rotation_scale changes */ gtk_signal_connect(GTK_OBJECT (rotation_scale), "value_changed", GTK_SIGNAL_FUNC(rotation_change), rotation_scale); gtk_widget_show (rotation); /* Lights label */ box2 = gtk_hbox_new (FALSE, 20); gtk_container_set_border_width (GTK_CONTAINER (box2), 10); gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0); gtk_widget_show (box2); label = gtk_label_new ("Lights:"); gtk_misc_set_alignment (GTK_MISC (label), 0, 0); gtk_box_pack_start (GTK_BOX (box2), label, FALSE, FALSE, 0); gtk_widget_show (label); /* Spotlight Intensity label */ box2 = gtk_hbox_new (FALSE, 20); gtk_container_set_border_width (GTK_CONTAINER (box2), 10); gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0); gtk_widget_show (box2); label = gtk_label_new (" Spotlight Intensity:"); gtk_misc_set_alignment (GTK_MISC (label), 0, 0); gtk_box_pack_start (GTK_BOX (box2), label, FALSE, FALSE, 0); gtk_widget_show (label); /* spotlight intensity scrollbar */ light_scale = (GtkAdjustment *)gtk_adjustment_new (1.0, 0.0, 1.0, 0.01, 0.2, 0.0); light_intensity = gtk_hscale_new( /*(GtkAdjustment *)*/ light_scale); gtk_widget_set_usize (GTK_WIDGET (light_intensity), 200, 30); gtk_box_pack_start (GTK_BOX (box2), light_intensity, TRUE, TRUE, 0); /** INSERT STATEMENT HERE TO CALL light_change WHENEVER light_scale CHANGES */ gtk_widget_show (light_intensity); /* ambient light scale */ /** USING ABOVE CODE AS AN EXAMPLE, ADD ambient_scale CODE **/ /** THE label SHOULD BE 'Ambient Intensity' **/ /** CREATE ambient_scale WITH INITIAL VALUE = 0.2, LOWEST VALUE = 0.0, HIGHEST VALUE = 1.0, AND INCREMENT = 0.01 **/ /** THE FUNCTION ambient_change SHOULD BE CALLED WHENEVER A CHANGE OCCURS IN ambient_scale **/ /* Sphere Color label */ box2 = gtk_hbox_new (FALSE, 20); gtk_container_set_border_width (GTK_CONTAINER (box2), 10); gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0); gtk_widget_show (box2); label = gtk_label_new ("Sphere Color:"); gtk_misc_set_alignment (GTK_MISC (label), 0, 0); gtk_box_pack_start (GTK_BOX (box2), label, FALSE, FALSE, 0); /** ADD A STATEMENT HERE TO MAKE THIS label APPEAR **/ /* red scale */ /** USING ABOVE CODE AS AN EXAMPLE, ADD red_scale CODE **/ /** THE label SHOULD BE ' R:' **/ /** CREATE red_scale WITH INITIAL VALUE = 1.0, LOWEST VALUE = 0.0, HIGHEST VALUE = 1.0, AND INCREMENT = 0.01 **/ /** THE FUNCTION red_change SHOULD BE CALLED WHENEVER A CHANGE OCCURS IN ambient_scale **/ /* green scale */ /* blue scale */ /** THE SAME SHOULD BE DONE FOR green_scale AND blue_scale, EXCEPT THEIR INITIAL VALUES SHOULD BE 0.0 **/ /* reset button */ reset_button = gtk_button_new_with_label("Reset All Values"); /* make the button call reset_button when clicked */ gtk_signal_connect(GTK_OBJECT(reset_button),"clicked", GTK_SIGNAL_FUNC(reset_controls),NULL); box2 = gtk_hbox_new (FALSE, 20); gtk_container_set_border_width (GTK_CONTAINER (box2), 10); gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (box2), reset_button, FALSE, FALSE, 0); gtk_widget_show (box2); /* ... Make the button visible ... */ gtk_widget_show(reset_button); /* quit button */ /** ADD A STATMENT TO CREATE THE quit_button WITH LABEL "Quit" **/ /** ADD A STATEMENT TO MAKE THE BUTTON CALL destroy_app WHEN CLICKED **/ /** UNCOMMENT THE FOLLOWING TWO LINES **/ /* gtk_box_pack_start (GTK_BOX (box2), quit_button, FALSE, FALSE, 0); gtk_widget_show (box2); */ /** ADD A STATEMENT TO MAKE THE BUTTON VISIBLE **/ } void draw_my_shapes () { GLfloat light_position [] = {3.0, 3.0, 3.0, 0.0}; GLfloat white [] = {1.0, 1.0, 1.0, 1.0}; GLfloat red [] = {1.0, 0.0, 0.0, 1.0}; int light1 = 0; GLUquadric *quad; /* LIGHTS */ /* spotlight */ glLightModeliv (GL_LIGHT_MODEL_LOCAL_VIEWER, &light1); glLightfv (GL_LIGHT0, GL_POSITION, light_position); glLightfv (GL_LIGHT0, GL_DIFFUSE, white_light); glLightfv (GL_LIGHT0, GL_AMBIENT, white_light); glLightfv (GL_LIGHT0, GL_SPECULAR, white_light); glEnable (GL_LIGHTING); glEnable (GL_LIGHT0); glEnable (GL_DEPTH_TEST); /* ambient light */ glLightModelfv (GL_LIGHT_MODEL_AMBIENT, amb_light); /* SPHERE */ /* sphere color */ glClear (GL_COLOR_BUFFER_BIT); glClearColor (0.0, 0.0, 0.0, 0.0); glShadeModel (GL_SMOOTH); /** CHANGE THE FOLLOWING STATEMENT SO THAT THE SPHERE IS SHADED BASED ON THE COLOR SLIDER VALUES RATHER THAN JUST BEING red ALL THE TIME **/ glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, red); amb_color [0] = color [0] / 5; amb_color [1] = color [1] / 5; amb_color [2] = color [2] / 5; amb_color [3] = color [3] / 5; glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT, amb_color); glMaterialfv (GL_FRONT, GL_SPECULAR, mat_specular); glMaterialfv (GL_FRONT, GL_SHININESS, mat_shininess); quad = gluNewQuadric (); glClear (GL_DEPTH_BUFFER_BIT); glutSolidSphere (1.0, 100, 100); /* AXES */ glClearColor (0.0, 0.0, 0.0, 0.0); glShadeModel (GL_SMOOTH); glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, white); glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT, white); glBegin (GL_LINES); glVertex3f (-3.0, 0.0, 0.0); glVertex3f (3.0, 0.0, 0.0); glEnd (); glBegin (GL_LINES); glVertex3f (0.0, -3.0, 0.0); glVertex3f (0.0, 3.0, 0.0); glEnd (); glBegin (GL_LINES); glVertex3f (0.0, 0.0, -3.0); glVertex3f (0.0, 0.0, 3.0); glEnd (); glFlush (); } gint redraw () { gtk_widget_grab_focus(GTK_WIDGET(glarea)); /* ... OpenGL calls can be done only if begingl returns true ... */ if (gtk_gl_area_begingl(GTK_GL_AREA(glarea))) { /* ... View ... */ glMatrixMode(GL_PROJECTION); glLoadIdentity(); /* 3D, not 2D */ gluPerspective(45.0, ((float) glarea->allocation.width) / glarea->allocation.height, 0.1,20.0); glDrawBuffer(GL_BACK); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); /* specify position for view volume -- look at origin, right-side up */ gluLookAt(lookat[0], lookat [1], lookat [2], 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); /* ... DRAW STUFF HERE ... */ glDrawBuffer(GL_BACK); draw_my_shapes (); /* opengl rendering done for now */ gtk_gl_area_endgl(GTK_GL_AREA(glarea)); } /* swap backbuffer to front */ gtk_gl_area_swapbuffers(GTK_GL_AREA(glarea)); return TRUE; } int main(int argc, char **argv) { GtkWidget *ctlwindow, *glwindow; /* ... Initialize gtk, handle command-line parameters ... */ gtk_init(&argc, &argv); /* ... Check if OpenGL (GLX extension) is supported. ... */ if(gdk_gl_query() == FALSE) { g_print("OpenGL not supported\n"); return(0); } ctlwindow = create_ctl_window(); if(!(glwindow = create_gl_window())) { g_print("Can't create GtkGlArea widget\n"); return(0); } /* ... This is the event loop in gtk ... */ /* ... Do not return until _gtk_main_quit_ is called ... */ gtk_main(); /* ... Exit status code ... */ return(0); }