Only in gnuplot-opengl_work/: Makefile Only in gnuplot-opengl_work/config: Makefile Only in gnuplot-opengl_work/: config.cache Only in gnuplot-opengl_work/: config.h Only in gnuplot-opengl_work/: config.log Only in gnuplot-opengl_work/: config.status Only in gnuplot-opengl_work/demo: Makefile Only in gnuplot-opengl_work/demo: binary1 Only in gnuplot-opengl_work/demo: binary2 Only in gnuplot-opengl_work/demo: binary3 Only in gnuplot-opengl_work/docs: Makefile Only in gnuplot-opengl_work/docs: doc2gih Only in gnuplot-opengl_work/docs: doc2gih.o Only in gnuplot-opengl_work/docs: gnuplot.gih Only in gnuplot-opengl_work/docs: termdoc.o Only in gnuplot-opengl_work/m4: Makefile Only in gnuplot-opengl_work/man: Makefile Only in gnuplot-opengl_work/src: Makefile diff -rc gnuplot-3.8b/src/Makefile.in gnuplot-opengl_work/src/Makefile.in *** gnuplot-3.8b/src/Makefile.in Sat Dec 11 06:01:00 1999 --- gnuplot-opengl_work/src/Makefile.in Mon Jan 17 16:45:02 2000 *************** *** 158,164 **** $(T)regis.trm $(T)rgip.trm $(T)sun.trm $(T)t410x.trm $(T)table.trm \ $(T)tek.trm $(T)texdraw.trm $(T)tgif.trm $(T)tkcanvas.trm $(T)tpic.trm \ $(T)unixpc.trm $(T)unixplot.trm $(T)v384.trm $(T)vws.trm $(T)win.trm \ ! $(T)x11.trm $(T)xlib.trm subdir = src mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs --- 158,164 ---- $(T)regis.trm $(T)rgip.trm $(T)sun.trm $(T)t410x.trm $(T)table.trm \ $(T)tek.trm $(T)texdraw.trm $(T)tgif.trm $(T)tkcanvas.trm $(T)tpic.trm \ $(T)unixpc.trm $(T)unixplot.trm $(T)v384.trm $(T)vws.trm $(T)win.trm \ ! $(T)x11.trm $(T)xlib.trm $(T)opengl.trm subdir = src mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs Only in gnuplot-opengl_work/src: alloc.o Only in gnuplot-opengl_work/src: bf_test Only in gnuplot-opengl_work/src: bf_test.o Only in gnuplot-opengl_work/src: binary.o Only in gnuplot-opengl_work/src: bitmap.o Only in gnuplot-opengl_work/src: command.o Only in gnuplot-opengl_work/src: contour.o Only in gnuplot-opengl_work/src: datafile.o Only in gnuplot-opengl_work/src: dynarray.o Only in gnuplot-opengl_work/src: eval.o Only in gnuplot-opengl_work/src: fit.o Only in gnuplot-opengl_work/src: gnuplot Only in gnuplot-opengl_work/src: gnuplot_opengl Only in gnuplot-opengl_work/src: gnuplot_x11 Only in gnuplot-opengl_work/src: gplt_x11.o diff -rc gnuplot-3.8b/src/graph3d.c gnuplot-opengl_work/src/graph3d.c *** gnuplot-3.8b/src/graph3d.c Thu Nov 25 00:24:33 1999 --- gnuplot-opengl_work/src/graph3d.c Fri Jan 21 22:44:13 2000 *************** *** 89,99 **** --- 89,105 ---- static void plot3d_impulses __PROTO((struct surface_points * plot)); static void plot3d_lines __PROTO((struct surface_points * plot)); + static void plotopengl_lines __PROTO((struct surface_points * plot)); + static void plotopengl_hiddenlines __PROTO((struct surface_points * plot)); + static void plotopengl_impulses __PROTO((struct surface_points * plot)); + static void plotopengl_surf __PROTO((struct surface_points * plot)); + static void plotopengl_points __PROTO((struct surface_points * plot)); static void plot3d_points __PROTO((struct surface_points * plot)); static void plot3d_dots __PROTO((struct surface_points * plot)); static void cntr3d_impulses __PROTO((struct gnuplot_contours * cntr, struct surface_points * plot)); static void cntr3d_lines __PROTO((struct gnuplot_contours * cntr)); + static void cntropengl_lines __PROTO((struct gnuplot_contours * cntr)); static void cntr3d_points __PROTO((struct gnuplot_contours * cntr, struct surface_points * plot)); static void cntr3d_dots __PROTO((struct gnuplot_contours * cntr)); *************** *** 101,108 **** --- 107,122 ---- double height[2][2], double depth[2][2])); static void draw_bottom_grid __PROTO((struct surface_points * plot, int plot_count)); + static void draw_bottom_grid_opengl __PROTO((struct surface_points * plot, + int plot_count)); static void xtick_callback __PROTO((int axis, double place, char *text, struct lp_style_type grid)); + static void xtick_callback_opengl __PROTO((int axis, double place, char *text, + struct lp_style_type grid)); + static void ytick_callback_opengl __PROTO((int axis, double place, char *text, + struct lp_style_type grid)); + static void ztick_callback_opengl __PROTO((int axis, double place, char *text, + struct lp_style_type grid)); static void ytick_callback __PROTO((int axis, double place, char *text, struct lp_style_type grid)); static void ztick_callback __PROTO((int axis, double place, char *text, *************** *** 439,444 **** --- 453,746 ---- static int key_size_left; /* distance from x to left edge of box */ static int key_size_right; /* distance from x to right edge of box */ + //#ifdef OPENGL + //---------------------------------------------------------------------------------- + //OPENGL part + //---------------------------------------------------------------------------------- + void + do_openglplot(plots,pcount) + struct surface_points *plots; + int pcount; + { + struct termentry *t = term; + int surface; + struct surface_points *this_plot = NULL; + unsigned int xl, yl; + int linetypeOffset = 0; + /* double ztemp, temp; unused */ + struct text_label *this_label; + struct arrow_def *this_arrow; + TBOOLEAN scaling; + transform_matrix mat; + int key_count; + char *s, *e; + + #define NEXT_KEY_LINE() \ + if ( ++key_count >= key_rows ) { \ + yl = yl_ref; xl += key_col_wth; key_count = 0; \ + } else \ + yl -= key_entry_height + + /* Initiate transformation matrix using the global view variables. */ + // Not implemented as yet? (we need to tell the opengl engine what are the + // viewing transformations. + /* mat_rot_z(surface_rot_z, trans_mat); + mat_rot_x(surface_rot_x, mat); + mat_mult(trans_mat, trans_mat, mat); + mat_scale(surface_scale / 2.0, surface_scale / 2.0, surface_scale / 2.0, mat); + mat_mult(trans_mat, trans_mat, mat); + */ + if (polar) + graph_error("Cannot splot in polar coordinate system."); + + /* If we are to draw the bottom grid make sure zmin is updated properly. */ + if (xtics || ytics || work_grid.l_type) { + base_z = z_min3d - (z_max3d - z_min3d) * ticslevel; + if (ticslevel >= 0) + floor_z = base_z; + else + floor_z = z_min3d; + + if (ticslevel < -1) + ceiling_z = base_z; + else + ceiling_z = z_max3d; + } else { + floor_z = base_z = z_min3d; + ceiling_z = z_max3d; + } + + /* see comment accompanying similar tests of x_min/x_max and y_min/y_max + * in graphics.c:do_plot(), for history/rationale of these tests */ + if (x_min3d == x_max3d) + graph_error("x_min3d should not equal x_max3d!"); + if (y_min3d == y_max3d) + graph_error("y_min3d should not equal y_max3d!"); + if (z_min3d == z_max3d) + graph_error("z_min3d should not equal z_max3d!"); + + term_start_plot(); + (*term->graphics)(); //clear current graph + + screen_ok = FALSE; + scaling = (*t->scale) (xsize, ysize); + + /* now compute boundary for plot (xleft, xright, ytop, ybot) */ + boundary3d(scaling, plots, pcount); + + /* SCALE FACTORS */ + zscale3d = 2.0 / (ceiling_z - floor_z) * surface_zscale; + yscale3d = 2.0 / (y_max3d - y_min3d); + xscale3d = 2.0 / (x_max3d - x_min3d); + + term_apply_lp_properties(&border_lp); /* border linetype */ + + /* PLACE TITLE */ + if (*title.text != 0) { + (*term->string)("F"); //Goto fixed coordinates + (*term->justify_text) (CENTRE); + (*term->put_text3d)(0+title.xoffset,0.55+title.yoffset,0,title.text); + (*term->string)("f"); + }; + + /* PLACE TIMEDATE */ + if (*timelabel.text) { + char str[MAX_LINE_LEN+1]; + time_t now; + time(&now); + strftime(str, MAX_LINE_LEN, timelabel.text, localtime(&now)); + (*term->string)("F"); //Goto fixed coordinates + (*term->justify_text) (LEFT); + (*term->put_text3d)(-0.53,-0.53,0.5,str); + (*term->string)("f"); + } + + /* DRAW SURFACES AND CONTOURS */ + + this_plot = plots; + for (surface = 0; + surface < pcount; + this_plot = this_plot->next_sp, surface++) { + + if (draw_surface) { + int lkey = (key != 0 && this_plot->title && this_plot->title[0]); + term_apply_lp_properties(&(this_plot->lp_properties)); + lkey=0; //temporarily ignore the key + + if (lkey) { + key_text(xl, yl, this_plot->title); + } + switch (this_plot->plot_style) { + case BOXES: /* can't do boxes in 3d yet so use impulses */ + case IMPULSES:{ + if (lkey) { + key_sample_line(xl, yl); + } + if (!(hidden3d && draw_surface)) + plotopengl_impulses(this_plot); + break; + } + case STEPS: /* HBB: I think these should be here */ + case FSTEPS: + case HISTEPS: + case LINES:{ + if (lkey) { + key_sample_line(xl, yl); + } + if (!(hidden3d && draw_surface)) + plotopengl_lines(this_plot); + else { + plotopengl_hiddenlines(this_plot); + (*t->linetype)(11); + plotopengl_surf(this_plot); + }; + + break; + } + case YERRORLINES: /* ignored; treat like points */ + case XERRORLINES: /* ignored; treat like points */ + case XYERRORLINES: /* ignored; treat like points */ + case YERRORBARS: /* ignored; treat like points */ + case XERRORBARS: /* ignored; treat like points */ + case XYERRORBARS: /* ignored; treat like points */ + case BOXXYERROR: /* HBB: ignore these as well */ + case BOXERROR: + case CANDLESTICKS: /* HBB: dito */ + case FINANCEBARS: + case VECTOR: + case POINTSTYLE: + if (lkey && !clip_point(xl + key_point_offset, yl)) { + key_sample_point(xl, yl, this_plot->lp_properties.p_type); + } + // if (!(hidden3d && draw_surface)) // irrelevant how can you hide + // pointstyle? + // (*term->point3d)(0,0,0,this_plot->lp_properties.p_type); + plotopengl_points(this_plot); + break; + + case LINESPOINTS: + //I am using this line style until it is decided how the surface should + //be implemented. I think there should be a new style defined like + //sp .. with poly or such. There should also be a new style to make + //quadratic surfaces. + if (lkey) { + key_sample_line(xl, yl); + } + // if (!(hidden3d && draw_surface)) + plotopengl_surf(this_plot); + // /* put lines */ + // if (lkey) + // key_sample_line(xl, yl); + // + // if (!(hidden3d && draw_surface)) + // plotopengl_lines(this_plot); + // + // /* put points */ + // if (lkey && !clip_point(xl + key_point_offset, yl)) + // key_sample_point(xl, yl, this_plot->lp_properties.p_type); + // + // if (!(hidden3d && draw_surface)) + // plot3d_points(this_plot); + + break; + + case DOTS: + if (lkey) { + if (key == 1) { + if (!clip_point(xl + key_point_offset, yl)) + (*t->point) (xl + key_point_offset, yl, -1); + } else { + (*t->point) (xl + key_point_offset, yl, -1); + /* (*t->point)(xl+2*(t->h_char),yl, -1); */ + } + } + // if (!(hidden3d && draw_surface)) + plot3d_dots(this_plot); + + break; + + } /* switch(plot-style) */ + + /* move key on a line */ + if (lkey) { + NEXT_KEY_LINE(); + } + } /* draw_surface */ + + /* Contours */ + if (draw_contour && this_plot->contours != NULL) { + struct gnuplot_contours *cntrs = this_plot->contours; + + term_apply_lp_properties(&(this_plot->lp_properties)); + (*t->linetype) (this_plot->lp_properties.l_type + (hidden3d ? 2 : 1)); + while(cntrs) { + if (label_contours && cntrs->isNewLevel) + (*t->linetype) (linetypeOffset++); + + switch (this_plot->plot_style) { + case IMPULSES: + case BOXES: /* HBB: this should also be treated somehow */ + cntr3d_impulses(cntrs, this_plot); + break; + case LINES: + case STEPS: /* HBB: these should also be handled, I think */ + case FSTEPS: + case HISTEPS: + cntropengl_lines(cntrs); + break; + case YERRORLINES: /* ignored; treat like points */ + case XERRORLINES: /* ignored; treat like points */ + case XYERRORLINES: /* ignored; treat like points */ + case YERRORBARS: /* ignored; treat like points */ + case XERRORBARS: /* ignored; treat like points */ + case XYERRORBARS: /* ignored; treat like points */ + case BOXERROR: /* HBB: ignore these too... */ + case BOXXYERROR: + case CANDLESTICKS: /* HBB: dito */ + case FINANCEBARS: + case VECTOR: + case POINTSTYLE: + cntr3d_points(cntrs, this_plot); + break; + case LINESPOINTS: + cntropengl_lines(cntrs); + cntr3d_points(cntrs, this_plot); + break; + case DOTS: + cntr3d_dots(cntrs); + break; + } /*switch */ + + cntrs = cntrs->next; + } /* loop over contours */ + } /* draw contours */ + } /* loop over surfaces */ + + draw_bottom_grid_opengl(plots, pcount); + // + // /* PLACE LABELS */ + // for (this_label = first_label; this_label != NULL; + // this_label = this_label->next) { + // unsigned int x, y; + // + // if (this_label->layer == 0) + // continue; + // map3d_position(&this_label->place, &x, &y, "label"); + // if (this_label->rotate && (*t->text_angle) (1)) { + // write_multiline(x, y, this_label->text, this_label->pos, CENTRE, 1, this_label->font); + // (*t->text_angle) (0); + // } else { + // write_multiline(x, y, this_label->text, this_label->pos, CENTRE, 0, this_label->font); + // } + // } + + + //Flush all data to force driver to plot: + (*term->text)(); + + }; + //#endif + void do_3dplot(plots, pcount) struct surface_points *plots; *************** *** 1093,1098 **** --- 1395,1531 ---- } } + + static void + plotopengl_surf(plot) + struct surface_points *plot; + { + int i,curve=0; + struct iso_curve *icrvs2,*icrvs = plot->iso_crvs; + struct coordinate GPHUGE *points,*points2; + // Only use isolines in the one direction, thats enough. + if(icrvs->next) icrvs2=icrvs->next; + else { printf("Only one isoline....\n"); + fflush(stdout); + return; //cant do much if there is only one isoline + }; + while (icrvs && icrvs2 && curve< plot->num_iso_read-1) { //the penultimate curve + points = icrvs->points; + points2 = icrvs2->points; + for (i = 0; i < icrvs->p_count-1; i++) + //No need to worry about range checks with opengl clipping.... + // if(points2[i].type==INRANGE || points[i].type==INRANGE || + // points[i+1].type==INRANGE ||points2[i+1].type==INRANGE ) //Make sure all + //the points in the surface are in range. + { + (*term->triangle)(1,map_x3d(points[i].x)/2,map_y3d(points[i].y)/2,map_z3d(points[i].z)/2, + map_x3d(points[i+1].x)/2,map_y3d(points[i+1].y)/2,map_z3d(points[i+1].z)/2, + map_x3d(points2[i].x)/2,map_y3d(points2[i].y)/2,map_z3d(points2[i].z)/2); + (*term->triangle)(1,map_x3d(points[i+1].x)/2,map_y3d(points[i+1].y)/2,map_z3d(points[i+1].z)/2, + map_x3d(points2[i+1].x)/2,map_y3d(points2[i+1].y)/2,map_z3d(points2[i+1].z)/2, + map_x3d(points2[i].x)/2,map_y3d(points2[i].y)/2,map_z3d(points2[i].z)/2); + }; + icrvs = icrvs->next; + icrvs2 = icrvs2->next; + curve++; + }; + }; + + static void + plotopengl_points(plot) + struct surface_points *plot; + { + int i,curve=0; + struct iso_curve *icrvs = plot->iso_crvs; + struct coordinate GPHUGE *points; + // Only use isolines in the one direction, thats enough. + while (icrvs && curve< plot->num_iso_read) { //the penultimate curve + points = icrvs->points; + for (i = 0; i < icrvs->p_count; i++) + // if(points[i].type==INRANGE) + (*term->point3d)(map_x3d(points[i].x)/2,map_y3d(points[i].y)/2,map_z3d(points[i].z)/2,plot->lp_properties.p_type); + // (*term->point3d)(0,0,0,0); + icrvs = icrvs->next; + curve++; + }; + }; + + static void + plotopengl_hiddenlines(plot) + struct surface_points *plot; + { + int i,curve=0; + struct iso_curve *icrvs2,*icrvs = plot->iso_crvs; + struct coordinate GPHUGE *points,*points2; + // Only use isolines in the one direction, thats enough. + if(icrvs->next) icrvs2=icrvs->next; + else { printf("Only one isoline....\n"); + fflush(stdout); + return; //cant do much if there is only one isoline + }; + while (icrvs && icrvs2 && curve< plot->num_iso_read-1) { //the penultimate curve + points = icrvs->points; + points2 = icrvs2->points; + for (i = 0; i < icrvs->p_count-1; i++) + // if(points[i].type==INRANGE) + { + (*term->move3d)(map_x3d(points[i].x)/2,map_y3d(points[i].y)/2,map_z3d(points[i].z)/2); + (*term->vector3d)(map_x3d(points[i+1].x)/2,map_y3d(points[i+1].y)/2,map_z3d(points[i+1].z)/2); + (*term->vector3d)(map_x3d(points2[i+1].x)/2,map_y3d(points2[i+1].y)/2,map_z3d(points2[i+1].z)/2); + (*term->vector3d)(map_x3d(points2[i].x)/2,map_y3d(points2[i].y)/2,map_z3d(points2[i].z)/2); + (*term->vector3d)(map_x3d(points[i].x)/2,map_y3d(points[i].y)/2,map_z3d(points[i].z)/2); + }; + icrvs = icrvs->next; + icrvs2 = icrvs2->next; + curve++; + }; + }; + + static void + plotopengl_lines(plot) + struct surface_points *plot; + { + int i; + struct iso_curve *icrvs = plot->iso_crvs; + struct coordinate GPHUGE *points; + + while (icrvs) { + points = icrvs->points; + (*term->move3d)(map_x3d(points[0].x)/2,map_y3d(points[0].y)/2,map_z3d(points[0].z)/2); + for (i = 0; i < icrvs->p_count; i++) + { + if(points[i].type!=UNDEFINED) + (*term->vector3d)(map_x3d(points[i].x)/2, map_y3d(points[i].y)/2,map_z3d(points[i].z)/2); + else + (*term->move3d)(map_x3d(points[i].x)/2,map_y3d(points[i].y)/2,map_z3d(points[i].z)/2); + }; + icrvs = icrvs->next; + }; + }; + + static void + plotopengl_impulses(plot) + struct surface_points *plot; + { + int i; + struct iso_curve *icrvs = plot->iso_crvs; + struct coordinate GPHUGE *points; + + while (icrvs) { + points = icrvs->points; + for (i = 0; i < icrvs->p_count-1; i++) + { + if(points[i].type!=UNDEFINED) + { + (*term->move3d)(map_x3d(points[i].x)/2,map_y3d(points[i].y)/2,map_z3d(0)/2); + (*term->vector3d)(map_x3d(points[i].x)/2, map_y3d(points[i].y/2),map_z3d(points[i].z)/2); + } + else + (*term->move3d)(map_x3d(points[i].x)/2,map_y3d(points[i].y)/2,map_z3d(points[i].z)/2); + }; + icrvs = icrvs->next; + }; + }; /* plot3d_lines: * Plot the surfaces in LINES style */ *************** *** 1284,1289 **** --- 1717,1752 ---- } } + static void + cntropengl_lines(cntr) + struct gnuplot_contours *cntr; + { + int i; /* point index */ + float x, y,z; /* point in terminal coordinates */ + + if (draw_contour & CONTOUR_SRF) { + for (i = 0; i < cntr->num_pts; i++) { + x=map_x3d(cntr->coords[i].x)/2; + y=map_y3d(cntr->coords[i].y)/2; + z=map_z3d(cntr->coords[i].z)/2; + // z=map_z3d(base_z); + + if (i) (*term->vector3d)(x,y,z); + else (*term->move3d)(x,y,z); + } + }; + + if (draw_contour & CONTOUR_BASE) { + for (i = 0; i < cntr->num_pts; i++) { + x=map_x3d(cntr->coords[i].x)/2; + y=map_y3d(cntr->coords[i].y)/2; + z=map_z3d(base_z)/2; + + if (i) (*term->vector3d)(x,y,z); + else (*term->move3d)(x,y,z); + } + } + } /* cntr3d_lines: * Plot a surface contour in LINES style */ *************** *** 1421,1426 **** --- 1884,2030 ---- } } + static void + draw_bottom_grid_opengl(plot,plot_num) + struct surface_points *plot; + int plot_num; + { + /* search surfaces for heights at corners */ + double height[2][2]; + double depth[2][2]; + double x[2][2]; + double y[2][2]; + int index; + + setlinestyle(border_lp); + if (draw_border &1 ) { + (*term->move3d) (map_x3d(x_min3d)/2,map_y3d(y_min3d)/2,map_z3d(base_z)/2); + (*term->vector3d)(map_x3d(x_max3d)/2,map_y3d(y_min3d)/2,map_z3d(base_z)/2); + }; + if (draw_border &2 ) { + (*term->move3d)(map_x3d(x_max3d)/2,map_y3d(y_min3d)/2,map_z3d(base_z)/2); + (*term->vector3d)(map_x3d(x_max3d)/2,map_y3d(y_max3d)/2,map_z3d(base_z)/2); + }; + if (draw_border &4 ) { + (*term->move3d)(map_x3d(x_max3d)/2,map_y3d(y_max3d)/2,map_z3d(base_z)/2); + (*term->vector3d)(map_x3d(x_min3d)/2,map_y3d(y_max3d)/2,map_z3d(base_z)/2); + }; + if (draw_border &8 ) { + (*term->move3d)(map_x3d(x_min3d)/2,map_y3d(y_max3d)/2,map_z3d(base_z)/2); + (*term->vector3d)(map_x3d(x_min3d)/2,map_y3d(y_min3d)/2,map_z3d(base_z)/2); + }; + if (draw_border &16 ) { + (*term->move3d)(map_x3d(x_min3d)/2,map_y3d(y_min3d)/2,map_z3d(base_z)/2); + (*term->vector3d)(map_x3d(x_min3d)/2,map_y3d(y_min3d)/2,map_z3d(ceiling_z)/2); + }; + if (draw_border &128 ) { + (*term->move3d)(map_x3d(x_min3d)/2,map_y3d(y_max3d)/2,map_z3d(base_z)/2); + (*term->vector3d)(map_x3d(x_min3d)/2,map_y3d(y_max3d)/2,map_z3d(ceiling_z)/2); + }; + if (draw_border &64 ) { + (*term->move3d)(map_x3d(x_max3d)/2,map_y3d(y_max3d)/2,map_z3d(base_z)/2); + (*term->vector3d)(map_x3d(x_max3d)/2,map_y3d(y_max3d)/2,map_z3d(ceiling_z)/2); + }; + if (draw_border &32 ) { + (*term->move3d)(map_x3d(x_max3d)/2,map_y3d(y_min3d)/2,map_z3d(base_z)/2); + (*term->vector3d)(map_x3d(x_max3d)/2,map_y3d(y_min3d)/2,map_z3d(ceiling_z)/2); + }; + if (draw_border &256 ) { + (*term->move3d) (map_x3d(x_min3d)/2,map_y3d(y_min3d)/2,map_z3d(ceiling_z)/2); + (*term->vector3d)(map_x3d(x_max3d)/2,map_y3d(y_min3d)/2,map_z3d(ceiling_z)/2); + }; + if (draw_border &512 ) { + (*term->move3d)(map_x3d(x_max3d)/2,map_y3d(y_min3d)/2,map_z3d(ceiling_z)/2); + (*term->vector3d)(map_x3d(x_max3d)/2,map_y3d(y_max3d)/2,map_z3d(ceiling_z)/2); + }; + if (draw_border &1024 ) { + (*term->move3d)(map_x3d(x_max3d)/2,map_y3d(y_max3d)/2,map_z3d(ceiling_z)/2); + (*term->vector3d)(map_x3d(x_min3d)/2,map_y3d(y_max3d)/2,map_z3d(ceiling_z)/2); + }; + if (draw_border &2048 ) { + (*term->move3d)(map_x3d(x_min3d)/2,map_y3d(y_max3d)/2,map_z3d(ceiling_z)/2); + (*term->vector3d)(map_x3d(x_min3d)/2,map_y3d(y_min3d)/2,map_z3d(ceiling_z)/2); + }; + height[0][0] = height[0][1] = height[1][0] = height[1][1] = base_z; + depth[0][0] = depth[0][1] = depth[1][0] = depth[1][1] = base_z; + x[0][0] = x[0][1] = x[1][0] = x[1][1] = x_min3d; + y[0][0] = y[0][1] = y[1][0] = y[1][1] = y_min3d; + + for (; --plot_num >= 0; plot = plot->next_sp) { + struct iso_curve *curve = plot->iso_crvs; + int count = curve->p_count; + int iso; + struct coordinate GPHUGE *p; + if (plot->plot_type == DATA3D) { + if (!plot->has_grid_topology) + continue; + iso = plot->num_iso_read; + } else + iso = iso_samples_2; + + p=curve->points; + x[0][0] = p->x; + y[0][0] = p->y; + height[0][0]=p->z; + p=curve->points+ count-1; + x[0][1] = p->x; + y[0][1] = p->y; + height[0][1]=p->z; + while (--iso) + curve = curve->next; + p=curve->points; + x[1][0] = p->x; + y[1][0] = p->y; + height[1][0]=p->z; + p=curve->points+ count-1; + x[1][1] = p->x; + y[1][1] = p->y; + height[1][1]=p->z; + }; + if(draw_border){ //This draws the lines from base_z to the surface. It + // seems that these lines are there regardless of draw_border. But are gone + // when draw_border==0. These lines are not well documented in the gnuplot + // help file. I hope I implemented these correctly. + int i,j; + for(i=0;i<2;i++) + for(j=0;j<2;j++) + { + (*term->move3d)(map_x3d(x[i][j])/2,map_y3d(y[i][j])/2,map_z3d(depth[i][j])/2); + (*term->vector3d)(map_x3d(x[i][j])/2,map_y3d(y[i][j])/2,map_z3d(height[i][j])/2); + }; + }; + + if (xtics) { + gen_tics(FIRST_X_AXIS, &xticdef, + work_grid.l_type & (GRID_X | GRID_MX), + mxtics, mxtfreq, xtick_callback_opengl); + }; + if (ytics) { + gen_tics(FIRST_Y_AXIS, &yticdef, + work_grid.l_type & (GRID_Y | GRID_MY), + mytics, mytfreq, ytick_callback_opengl); + }; + if (ztics && (draw_surface || (draw_contour & CONTOUR_SRF))) { + gen_tics(FIRST_Z_AXIS, &zticdef, work_grid.l_type & (GRID_Z | GRID_MZ), + mztics, mztfreq, ztick_callback_opengl); + }; + + }; + // } + // if (*xlabel.text) { + // /* label at xaxis_y + 1/4 of (xaxis_y-other_y) */ + // double step = (2 * xaxis_y - y_max3d - y_min3d) / 4; + // map3d_xy(mid_x, xaxis_y + step, base_z, &x1, &y1); + // x1 += xlabel.xoffset * t->h_char; + // y1 += xlabel.yoffset * t->v_char; + // if (!tic_in) { + // x1 -= tic_unitx * ticscale * (t->h_tic); + // y1 -= tic_unity * ticscale * (t->v_tic); + // } + // /* write_multiline mods it */ + // write_multiline(x1, y1, xlabel.text, CENTRE, JUST_TOP, 0, xlabel.font); + // } + // } /* Draw the bottom grid that hold the tic marks for 3d surface. */ static void *************** *** 1703,1708 **** --- 2307,2388 ---- } } + #define OPENGL_TIC_FACTOR 60 //100/60 percent of full length + + static void + ytick_callback_opengl(axis, place, text, grid) + int axis; + double place; + char *text; + struct lp_style_type grid; /* linetype or -2 for none */ + { + unsigned int x, y, x1, y1; + int tmp; + double scale = (text ? ticscale : miniticscale); + int dirn = tic_in ? 1 : -1; + register struct termentry *t = term; + + if (grid.l_type > -2) { + term_apply_lp_properties(&grid); + (*term->move3d) (map_y3d(x_min3d)/2,map_x3d(place)/2,map_z3d(base_z)/2); + (*term->vector3d)(map_y3d(x_max3d)/2,map_x3d(place)/2,map_z3d(base_z)/2); + + term_apply_lp_properties(&border_lp); + } + if (ytics & TICS_ON_AXIS) + tmp=yaxis_x; + else + tmp=x_min3d; + (*term->move3d) (map_x3d(tmp)/2,map_y3d(place)/2,map_z3d(base_z)/2); + (*term->vector3d)(map_x3d(tmp+scale*dirn*(x_max3d-x_min3d)/OPENGL_TIC_FACTOR)/2,map_y3d(place)/2,map_z3d(base_z)/2); + + if (ytics & TICS_MIRROR) { + (*term->move3d) (map_x3d(x_max3d)/2,map_y3d(place)/2,map_z3d(base_z)/2); + (*term->vector3d)(map_x3d(x_max3d-scale*dirn*(x_max3d-x_min3d)/OPENGL_TIC_FACTOR)/2,map_y3d(place)/2,map_z3d(base_z)/2); + } + if (text) { + (*term->justify_text)(LEFT); + (*term->put_text3d)(map_x3d(x_max3d)/2+0.05,map_y3d(place)/2,map_z3d(base_z)/2-0.05,text); + } + } + + static void + xtick_callback_opengl(axis, place, text, grid) + int axis; + double place; + char *text; + struct lp_style_type grid; /* linetype or -2 for none */ + { + unsigned int x, y, x1, y1; + int tmp; + double scale = (text ? ticscale : miniticscale); + int dirn = tic_in ? 1 : -1; + register struct termentry *t = term; + + if (grid.l_type > -2) { + term_apply_lp_properties(&grid); + (*term->move3d) (map_x3d(place)/2,map_y3d(y_min3d)/2,map_z3d(base_z)/2); + (*term->vector3d)(map_x3d(place)/2,map_y3d(y_max3d)/2,map_z3d(base_z)/2); + term_apply_lp_properties(&border_lp); + } + if (xtics & TICS_ON_AXIS) + tmp=xaxis_y; + else + tmp=y_min3d; + (*term->move3d) (map_x3d(place)/2,map_y3d(tmp)/2,map_z3d(base_z)/2); + (*term->vector3d)(map_x3d(place)/2,map_y3d(tmp+scale*dirn*(y_max3d-y_min3d)/OPENGL_TIC_FACTOR)/2,map_z3d(base_z)/2); + + if (xtics & TICS_MIRROR) { + (*term->move3d) (map_x3d(place)/2,map_y3d(y_max3d)/2,map_z3d(base_z)/2); + (*term->vector3d)(map_x3d(place)/2,map_y3d(y_max3d-scale*dirn*(y_max3d-y_min3d)/OPENGL_TIC_FACTOR)/2,map_z3d(base_z)/2); + } + if (text) { + (*term->justify_text)(LEFT); + // (*term->move3d)(map_x3d(place)/2,map_y3d(y_min3d)/2,map_z3d(base_z)/2); + // (*term->vector3d)(map_x3d(place)/2,map_y3d(y_min3d)/2-0.05,map_z3d(base_z)/2-0.05); + (*term->put_text3d)(map_x3d(place)/2,map_y3d(y_min3d)/2-0.05,map_z3d(base_z)/2-0.05,text); + } + } static void xtick_callback(axis, place, text, grid) *************** *** 1813,1818 **** --- 2493,2532 ---- x1 = x - tic_unitx * scale * (t->h_tic) * dirn; y1 = y - tic_unity * scale * (t->v_tic) * dirn; draw_clip_line(x, y, x1, y1); + } + } + + static void + ztick_callback_opengl(axis, place, text, grid) + int axis; + double place; + char *text; + struct lp_style_type grid; + { + /* HBB: inserted some ()'s to shut up gcc -Wall, here and below */ + int len = (text ? ticscale : miniticscale) * (tic_in ? 1 : -1) * (term->h_tic); + double scale = (text ? ticscale : miniticscale); + unsigned int x, y; + double other_x = x_min3d + x_max3d - zaxis_x; + double other_y = y_min3d + y_max3d - zaxis_y; + + if (grid.l_type > -2) { + term_apply_lp_properties(&grid); + (*term->move3d) (map_x3d(zaxis_x)/2,map_y3d(zaxis_y)/2,map_z3d(place)/2); + (*term->vector3d)(map_x3d(back_x)/2,map_y3d(back_y)/2,map_z3d(place)/2); + (*term->vector3d)(map_x3d(other_x)/2,map_y3d(other_y)/2,map_z3d(place)/2); + term_apply_lp_properties(&border_lp); + } + (*term->move3d) (map_x3d(x_min3d)/2,map_y3d(y_min3d)/2,map_z3d(place)/2); + (*term->vector3d)(map_x3d(x_min3d+scale*(x_max3d-x_min3d)/OPENGL_TIC_FACTOR)/2,map_y3d(y_min3d+scale*(y_max3d-y_min3d)/OPENGL_TIC_FACTOR)/2,map_z3d(place)/2); + if (text) { + (*term->justify_text)(LEFT); + + (*term->put_text3d) (map_x3d(x_min3d)/2-0.05,map_y3d(y_min3d)/2-0.05,map_z3d(place)/2,text); + } + if (ztics & TICS_MIRROR) { + (*term->move3d) (map_x3d(other_x)/2,map_y3d(other_y)/2,map_z3d(place)/2); + (*term->vector3d)(map_x3d(other_x-scale*(x_max3d-x_min3d)/OPENGL_TIC_FACTOR)/2,map_y3d(other_y-scale*(y_max3d-y_min3d)/OPENGL_TIC_FACTOR)/2,map_z3d(place)/2); } } Only in gnuplot-opengl_work/src: graph3d.c~ Only in gnuplot-opengl_work/src: graph3d.o Only in gnuplot-opengl_work/src: graphics.o Only in gnuplot-opengl_work/src: help.o Only in gnuplot-opengl_work/src: hidden3d.o Only in gnuplot-opengl_work/src: history.o Only in gnuplot-opengl_work/src: internal.o Only in gnuplot-opengl_work/src: interpol.o Only in gnuplot-opengl_work/src: matrix.o Only in gnuplot-opengl_work/src: misc.o diff -rc gnuplot-3.8b/src/opengl/Makefile gnuplot-opengl_work/src/opengl/Makefile *** gnuplot-3.8b/src/opengl/Makefile Sat Jan 22 22:20:01 2000 --- gnuplot-opengl_work/src/opengl/Makefile Sat Jan 22 22:20:20 2000 *************** *** 0 **** --- 1,33 ---- + INCDIR = /usr/include + LIBDIR = /usr/lib + + GL_LIBS = -L$(LIBDIR) -lglut -lMesaGLU -lMesaGL -lm -L/usr/X11/lib -lX11 -lXext -lXmu -lXi + + PROGS = gnuplot_opengl Feedback + CCODE = model.c cube.c gnuplot_opengl.c + INCLUDES = vector.h + + ##### TARGETS ##### + gnuplot_opengl: gnuplot_opengl.o gl2ps.o + g++ -DnDEBUG -Wall -g -I$(INCDIR) $(CFLAGS) gnuplot_opengl.o gl2ps.o $(GL_LIBS) -o ../$@ + #libglut.a libMesaGLU.a libMesaGL.a + + clean: + -rm *.o *~ + + realclean: + -rm $(PROGS) + -rm *.o *~ + + targets: $(PROGS) + gnuplot_opengl.o: gnuplot_opengl.c + g++ -DnDEBUG -Wall -g -c -I$(INCDIR) $(CFLAGS) gnuplot_opengl.c + + gl2ps.o: gl2ps.c + g++ -DnDEBUG -Wall -g -c -I$(INCDIR) $(CFLAGS) gl2ps.c + + + Feedback: Feedback.c + g++ -DnDEBUG -Wall -g -I$(INCDIR) $(CFLAGS) Feedback.c $(GL_LIBS) -o $@ + + all: $(PROGS) diff -rc gnuplot-3.8b/src/opengl/Makefile.dynamic gnuplot-opengl_work/src/opengl/Makefile.dynamic *** gnuplot-3.8b/src/opengl/Makefile.dynamic Sat Jan 22 22:20:01 2000 --- gnuplot-opengl_work/src/opengl/Makefile.dynamic Fri Jan 21 21:48:28 2000 *************** *** 0 **** --- 1,33 ---- + INCDIR = /usr/include + LIBDIR = /usr/lib + + GL_LIBS = -L$(LIBDIR) -lglut -lMesaGLU -lMesaGL -lm -L/usr/X11/lib -lX11 -lXext -lXmu -lXi + + PROGS = gnuplot_opengl Feedback + CCODE = model.c cube.c gnuplot_opengl.c + INCLUDES = vector.h + + ##### TARGETS ##### + gnuplot_opengl: gnuplot_opengl.o gl2ps.o + g++ -DnDEBUG -Wall -g -I$(INCDIR) $(CFLAGS) gnuplot_opengl.o gl2ps.o $(GL_LIBS) -o ../$@ + #libglut.a libMesaGLU.a libMesaGL.a + + clean: + -rm *.o *~ + + realclean: + -rm $(PROGS) + -rm *.o *~ + + targets: $(PROGS) + gnuplot_opengl.o: gnuplot_opengl.c + g++ -DnDEBUG -Wall -g -c -I$(INCDIR) $(CFLAGS) gnuplot_opengl.c + + gl2ps.o: gl2ps.c + g++ -DnDEBUG -Wall -g -c -I$(INCDIR) $(CFLAGS) gl2ps.c + + + Feedback: Feedback.c + g++ -DnDEBUG -Wall -g -I$(INCDIR) $(CFLAGS) Feedback.c $(GL_LIBS) -o $@ + + all: $(PROGS) diff -rc gnuplot-3.8b/src/opengl/Makefile.static gnuplot-opengl_work/src/opengl/Makefile.static *** gnuplot-3.8b/src/opengl/Makefile.static Sat Jan 22 22:20:01 2000 --- gnuplot-opengl_work/src/opengl/Makefile.static Sat Jan 22 18:40:05 2000 *************** *** 0 **** --- 1,32 ---- + INCDIR = /usr/include + LIBDIR = /usr/lib + + GL_LIBS = -L$(LIBDIR) -lm -L/usr/X11/lib -lX11 -lXext -lXmu -lXi + + PROGS = gnuplot_opengl Feedback + CCODE = model.c cube.c gnuplot_opengl.c + INCLUDES = vector.h + + ##### TARGETS ##### + gnuplot_opengl: gnuplot_opengl.o gl2ps.o + g++ -DnDEBUG -Wall -g -I$(INCDIR) $(CFLAGS) gnuplot_opengl.o gl2ps.o libglut.a libMesaGLU.a libMesaGL.a $(GL_LIBS) -o ../$@ + + clean: + -rm *.o *~ + + realclean: + -rm $(PROGS) + -rm *.o *~ + + targets: $(PROGS) + gnuplot_opengl.o: gnuplot_opengl.c + g++ -DnDEBUG -Wall -g -c -I$(INCDIR) $(CFLAGS) gnuplot_opengl.c + + gl2ps.o: gl2ps.c + g++ -DnDEBUG -Wall -g -c -I$(INCDIR) $(CFLAGS) gl2ps.c + + + Feedback: Feedback.c + g++ -DnDEBUG -Wall -g -I$(INCDIR) $(CFLAGS) Feedback.c $(GL_LIBS) -o $@ + + all: $(PROGS) Only in gnuplot-opengl_work/src/opengl: Makefile~ Only in gnuplot-opengl_work/src/opengl: README Only in gnuplot-opengl_work/src/opengl: README~ diff -rc gnuplot-3.8b/src/opengl/changelog gnuplot-opengl_work/src/opengl/changelog *** gnuplot-3.8b/src/opengl/changelog Sat Jan 22 22:20:01 2000 --- gnuplot-opengl_work/src/opengl/changelog Sat Jan 22 22:08:49 2000 *************** *** 0 **** --- 1,63 ---- + version 0.04 + - Improved implementation of colormaps. Now a tessalation algorithm splits + triangles at colormap boundaries, so that large triangles are colormapped + properly. This has a huge visual impact on the quality of surface plots. + (Colormaps could also be implemented as 1D textures, but I did a test on + software rendered Cel400, and got a performance degradation of 3-4 times. I + thought this was unacceptable. On hardware accelerated platforms, I think the + degradation should be minimal.) + - Added clipping planes around the graph. Now gnuplot deliberately plots + isolines and samples outside the graph to allow for a display of a partial + surface square.Hence removed most of "if (..==INRANGE)" in opengl code. + - Made hidden surface not selectable by user. + - Grid,xtic,ytic,ztics now work in 3D graph. + - changed function of right mouse button to bring up a menu. + - Translation is now done by pressing the shift key and dragging. + - Added a watch cursor while input is read from gnuplot, rotate and scale + cursors when image is manipulated. + - tick text now works for all axes. I intend to make the text positioning a + little more intelligent to avoid text collisions with axes. + - Added a write to eps file using Mark J. Kilgard's example post on the SGI + website. Now it is possible to save images directly to eps using right mouse + button. Implemented line width in eps, but no text as yet. + + version 0.03 + - Added 12 different surface types (colormaps). Includes Hot, cool, HSV, + copper, and many others. + - surface colormap is now selected by using a line type: sp .. w linesp x + where x is -1 to 12. + - Fixed GL_DEPTH_BIT clear bug, which seemed to come out on everyone's Mesa + libabry except mine (?). Solves Black screen problem + - Fixed bug where if gnuplot crashed the opengl engine hangs reporting "I do + not understand" (the input pipe). It now exits gracefully. + - Implemented hidden3d internally by using a black surface (or white if the bg + is white) and an overlapping lines plot. So now it is possible to + "set hidden" and "sp ... w lines" as expected. + - Fixed up the makefile for making gnuplot_opengl.c (contributed). + - Added option to set term called "white" which sets the background white, and + changes the first 3 linestyles to black, for a reverse video effect. + - Added keyboard bindings for navigation, now arrows and HOME and PGUP control + rotation, while +/- control step size. SHIFT arrows translates, and shift +/- + zooms. + - Added key binding for 'v': resets view in graph so that the graph's z axis + is alligned with the screen's y coordinate. Note that holding v, while + dragging the mouse is equivalent to only having 2 degrees of freedom as is + the case with gnuoplot. + - Added support for title,timestamp in 3D graphs. + - Contours now work in 3D graphs on surfaces and base. + + version 0.02 + - Fixed inefficient search routine for linked list- significantly reduces time + between issuing a large plot command to the driver actually plotting it. + - Removed fflush statements in the opengl in board driver. and added an fflash + in the term->text routine. + - Added a term->text call at the end of the 3d plotting routine to force pipe flush. + - Added a polygon offset to enable plots with lines and surfaces without + stitching. + - used glutPostRedisplay to make animation much smoother. The interface is + really responsive even at very low frame rates. + - fixed it to allow many light sources on the command line. + + + version 0.01 + First release. Only in gnuplot-opengl_work/src/opengl: changelog~ diff -rc gnuplot-3.8b/src/opengl/gl2ps.c gnuplot-opengl_work/src/opengl/gl2ps.c *** gnuplot-3.8b/src/opengl/gl2ps.c Sat Jan 22 22:20:01 2000 --- gnuplot-opengl_work/src/opengl/gl2ps.c Sat Jan 22 22:11:05 2000 *************** *** 0 **** --- 1,587 ---- + /* Copyright (c) Mark J. Kilgard, 1997. Hacked by Michael Cohen for + * gnuplot-opengl 2000 */ + + /* This program is freely distributable without licensing fees + and is provided without guarantee or warrantee expressed or + implied. This program is -not- in the public domain. */ + + #include + #include + #include + #include + #include + + //Prototypes + extern void render(void); + + + typedef struct _DepthIndex { + GLfloat *ptr; + GLfloat depth; + GLfloat width; //each line segment needs to preserve the width it came with. + } DepthIndex; + + /* OpenGL's GL_3D_COLOR feedback vertex format. */ + typedef struct _Feedback3Dcolor { + GLfloat x; + GLfloat y; + GLfloat z; + GLfloat red; + GLfloat green; + GLfloat blue; + GLfloat alpha; + } Feedback3Dcolor; + + int blackBackground = 0; /* Initially use a white background. */ + int lighting = 0; /* Initially disable lighting. */ + int polygonMode = 1; /* Initially show wireframe. */ + int object = 1; /* Initially show the torus. */ + GLfloat width=1; + + GLfloat angle = 0.0; /* Angle of rotation for object. */ + int moving, begin; /* For interactive object rotation. */ + int size = 1; /* Size of lines and points. */ + + /* How many feedback buffer GLfloats each of the three objects need. */ + int objectComplexity[3] = + {6000, 14000, 380000}; /* Teapot requires ~1.5 megabytes for + its feedback results! */ + + void + updateBackground(void) + { + if (blackBackground) { + /* Clear to black. */ + glClearColor(0.0, 0.0, 0.0, 1.0); + } else { + /* Clear to white. */ + glClearColor(1.0, 1.0, 1.0, 1.0); + } + } + + void + updateLighting(void) + { + if (lighting) { + glEnable(GL_LIGHTING); + } else { + glDisable(GL_LIGHTING); + } + } + + void + updatePolygonMode(void) + { + switch (polygonMode) { + case 0: + glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); + break; + case 1: + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + break; + case 2: + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + break; + } + } + + /* Write contents of one vertex to stdout. */ + void + print3DcolorVertex(GLint size, GLint * count, + GLfloat * buffer) + { + int i; + + printf(" "); + for (i = 0; i < 7; i++) { + printf("%4.2f ", buffer[size - (*count)]); + *count = *count - 1; + } + printf("\n"); + } + + void + printBuffer(GLint size, GLfloat * buffer) + { + GLint count; + int token, nvertices; + + count = size; + while (count) { + token = (int) buffer[size - count]; + count--; + switch (token) { + case GL_PASS_THROUGH_TOKEN: + printf("GL_PASS_THROUGH_TOKEN\n"); + printf(" %4.2f\n", buffer[size - count]); + count--; + break; + case GL_POINT_TOKEN: + printf("GL_POINT_TOKEN\n"); + print3DcolorVertex(size, &count, buffer); + break; + case GL_LINE_TOKEN: + printf("GL_LINE_TOKEN\n"); + print3DcolorVertex(size, &count, buffer); + print3DcolorVertex(size, &count, buffer); + break; + case GL_LINE_RESET_TOKEN: + printf("GL_LINE_RESET_TOKEN\n"); + print3DcolorVertex(size, &count, buffer); + print3DcolorVertex(size, &count, buffer); + break; + case GL_BITMAP_TOKEN: + printf("GL_BITMAP_TOKEN\n"); + print3DcolorVertex(size, &count, buffer); + break; + case GL_POLYGON_TOKEN: + printf("GL_POLYGON_TOKEN\n"); + nvertices = (int) buffer[size - count]; + count--; + for (; nvertices > 0; nvertices--) { + print3DcolorVertex(size, &count, buffer); + } + } + } + } + + GLfloat pointSize; + + static char *gouraudtriangleEPS[] = + { + "/bd{bind def}bind def /triangle { aload pop setrgbcolor aload pop 5 3", + "roll 4 2 roll 3 2 roll exch moveto lineto lineto closepath fill } bd", + "/computediff1 { 2 copy sub abs threshold ge {pop pop pop true} { exch 2", + "index sub abs threshold ge { pop pop true} { sub abs threshold ge } ifelse", + "} ifelse } bd /computediff3 { 3 copy 0 get 3 1 roll 0 get 3 1 roll 0 get", + "computediff1 {true} { 3 copy 1 get 3 1 roll 1 get 3 1 roll 1 get", + "computediff1 {true} { 3 copy 2 get 3 1 roll 2 get 3 1 roll 2 get", + "computediff1 } ifelse } ifelse } bd /middlecolor { aload pop 4 -1 roll", + "aload pop 4 -1 roll add 2 div 5 1 roll 3 -1 roll add 2 div 3 1 roll add 2", + "div 3 1 roll exch 3 array astore } bd /gouraudtriangle { computediff3 { 4", + "-1 roll aload 7 1 roll 6 -1 roll pop 3 -1 roll pop add 2 div 3 1 roll add", + "2 div exch 3 -1 roll aload 7 1 roll exch pop 4 -1 roll pop add 2 div 3 1", + "roll add 2 div exch 3 -1 roll aload 7 1 roll pop 3 -1 roll pop add 2 div 3", + "1 roll add 2 div exch 7 3 roll 10 -3 roll dup 3 index middlecolor 4 1 roll", + "2 copy middlecolor 4 1 roll 3 copy pop middlecolor 4 1 roll 13 -1 roll", + "aload pop 17 index 6 index 15 index 19 index 6 index 17 index 6 array", + "astore 10 index 10 index 14 index gouraudtriangle 17 index 5 index 17", + "index 19 index 5 index 19 index 6 array astore 10 index 9 index 13 index", + "gouraudtriangle 13 index 16 index 5 index 15 index 18 index 5 index 6", + "array astore 12 index 12 index 9 index gouraudtriangle 17 index 16 index", + "15 index 19 index 18 index 17 index 6 array astore 10 index 12 index 14", + "index gouraudtriangle 18 {pop} repeat } { aload pop 5 3 roll aload pop 7 3", + "roll aload pop 9 3 roll 4 index 6 index 4 index add add 3 div 10 1 roll 7", + "index 5 index 3 index add add 3 div 10 1 roll 6 index 4 index 2 index add", + "add 3 div 10 1 roll 9 {pop} repeat 3 array astore triangle } ifelse } bd", + "/vshift -46 def /Solid false def /Color false def /DL { Color ", + "{setrgbcolor Solid {pop []} if 0 setdash }{pop pop pop Solid {pop []} if", + "0 setdash} ifelse } def /gnulinewidth 5.000 def /Lshow { currentpoint stroke M", + "0 vshift R show } def /UL { gnulinewidth mul /userlinewidth exch def } def", + "/BL { stroke gnulinewidth 2 mul setlinewidth } def /LTb { BL [] 0 0 0 DL } def", + "/M {moveto} bind def /R {rmoveto} bind def (Helvetica) findfont 14 scalefont setfont", + // "LTb 216.938 116.784 moveto gsave 0 setgray (Terminal Test) Lshow grestore", + NULL + }; + + GLfloat * + spewPrimitiveEPS(FILE * file, _DepthIndex prims ) + { + int token; + int nvertices, i; + GLfloat red, green, blue; + int smooth; + GLfloat dx, dy, dr, dg, db, absR, absG, absB, colormax; + int steps; + Feedback3Dcolor *vertex; + GLfloat xstep, ystep, rstep, gstep, bstep; + GLfloat xnext, ynext, rnext, gnext, bnext, distance; + + GLfloat *loc = prims.ptr; + token = (int) *loc; + loc++; + switch (token) { + case GL_LINE_RESET_TOKEN: + case GL_LINE_TOKEN: + vertex = (Feedback3Dcolor *) loc; + + dr = vertex[1].red - vertex[0].red; + dg = vertex[1].green - vertex[0].green; + db = vertex[1].blue - vertex[0].blue; + + if (dr != 0 || dg != 0 || db != 0) { + /* Smooth shaded line. */ + dx = vertex[1].x - vertex[0].x; + dy = vertex[1].y - vertex[0].y; + distance = sqrt(dx * dx + dy * dy); + + absR = fabs(dr); + absG = fabs(dg); + absB = fabs(db); + + #define Max(a,b) (((a)>(b))?(a):(b)) + + #define EPS_SMOOTH_LINE_FACTOR 0.06 /* Lower for better smooth + + lines. */ + + colormax = Max(absR, Max(absG, absB)); + steps = (int) Max(1.0, colormax * distance * EPS_SMOOTH_LINE_FACTOR); + + xstep = dx / steps; + ystep = dy / steps; + + rstep = dr / steps; + gstep = dg / steps; + bstep = db / steps; + + xnext = vertex[0].x; + ynext = vertex[0].y; + rnext = vertex[0].red; + gnext = vertex[0].green; + bnext = vertex[0].blue; + + /* Back up half a step; we want the end points to be + exactly the their endpoint colors. */ + xnext -= xstep / 2.0; + ynext -= ystep / 2.0; + rnext -= rstep / 2.0; + gnext -= gstep / 2.0; + bnext -= bstep / 2.0; + } else { + /* Single color line. */ + steps = 0; + } + + fprintf(file, "%g %g %g setrgbcolor\n", + vertex[0].red, vertex[0].green, vertex[0].blue); + if(prims.width!=width){ + fprintf(file, "%g setlinewidth\n",prims.width); + width=prims.width; + }; + + fprintf(file, "%g %g moveto\n", vertex[0].x, vertex[0].y); + + for (i = 0; i < steps; i++) { + xnext += xstep; + ynext += ystep; + rnext += rstep; + gnext += gstep; + bnext += bstep; + fprintf(file, "%g %g lineto stroke\n", xnext, ynext); + fprintf(file, "%g %g %g setrgbcolor\n", rnext, gnext, bnext); + fprintf(file, "%g %g moveto\n", xnext, ynext); + } + fprintf(file, "%g %g lineto stroke\n", vertex[1].x, vertex[1].y); + + loc += 14; /* Each vertex element in the feedback + buffer is 7 GLfloats. */ + + break; + case GL_POLYGON_TOKEN: + nvertices = (int) *loc; + loc++; + + vertex = (Feedback3Dcolor *) loc; + + if (nvertices > 0) { + red = vertex[0].red; + green = vertex[0].green; + blue = vertex[0].blue; + smooth = 0; + for (i = 1; i < nvertices; i++) { + if (red != vertex[i].red || green != vertex[i].green || blue != vertex[i].blue) { + smooth = 1; + break; + } + } + if (smooth) { + /* Smooth shaded polygon; varying colors at vetices. */ + int triOffset; + + /* Break polygon into "nvertices-2" triangle fans. */ + for (i = 0; i < nvertices - 2; i++) { + triOffset = i * 7; + fprintf(file, "[%g %g %g %g %g %g]", + vertex[0].x, vertex[i + 1].x, vertex[i + 2].x, + vertex[0].y, vertex[i + 1].y, vertex[i + 2].y); + fprintf(file, " [%g %g %g] [%g %g %g] [%g %g %g] gouraudtriangle\n", + vertex[0].red, vertex[0].green, vertex[0].blue, + vertex[i + 1].red, vertex[i + 1].green, vertex[i + 1].blue, + vertex[i + 2].red, vertex[i + 2].green, vertex[i + 2].blue); + } + } else { + /* Flat shaded polygon; all vertex colors the same. */ + fprintf(file, "newpath\n"); + fprintf(file, "%g %g %g setrgbcolor\n", red, green, blue); + + /* Draw a filled triangle. */ + fprintf(file, "%g %g moveto\n", vertex[0].x, vertex[0].y); + for (i = 1; i < nvertices; i++) { + fprintf(file, "%g %g lineto\n", vertex[i].x, vertex[i].y); + } + fprintf(file, "closepath fill\n\n"); + } + } + loc += nvertices * 7; /* Each vertex element in the + feedback buffer is 7 GLfloats. */ + break; + case GL_POINT_TOKEN: + vertex = (Feedback3Dcolor *) loc; + fprintf(file, "%g %g %g setrgbcolor\n", vertex[0].red, vertex[0].green, vertex[0].blue); + fprintf(file, "%g %g %g 0 360 arc fill\n\n", vertex[0].x, vertex[0].y, pointSize / 2.0); + loc += 7; /* Each vertex element in the feedback + buffer is 7 GLfloats. */ + break; + case GL_BITMAP_TOKEN: + printf("Cant do Text characters yet!!! Character dropped\n"); + fflush(stdout); + loc += 7; + default: + /* XXX Left as an excersie to the reader. */ + printf("Incomplete implementation 1. Unexpected token (%d).\n", token); + exit(1); + } + return loc; + } + + static int + compare(const void *a, const void *b) + { + DepthIndex *p1 = (DepthIndex *) a; + DepthIndex *p2 = (DepthIndex *) b; + GLfloat diff = p2->depth - p1->depth; + + if (diff > 0.0) { + return 1; + } else if (diff < 0.0) { + return -1; + } else { + return 0; + } + } + + void + spewSortedFeedback(FILE * file, GLint size, GLfloat * buffer) + { + int token; + GLfloat *loc, *end; + Feedback3Dcolor *vertex; + GLfloat depthSum; + int nprimitives, item; + DepthIndex *prims; + int nvertices, i; + + end = buffer + size; + + /* Count how many primitives there are. */ + nprimitives = 0; + loc = buffer; + while (loc < end) { + token = (int) *loc; + loc++; + switch (token) { + case GL_LINE_TOKEN: + case GL_LINE_RESET_TOKEN: + loc += 14; + nprimitives++; + break; + case GL_POLYGON_TOKEN: + nvertices = (int) *loc; + loc++; + loc += (7 * nvertices); + nprimitives++; + break; + case GL_POINT_TOKEN: + loc += 7; + nprimitives++; + break; + case GL_PASS_THROUGH_TOKEN: + loc += 1; + break; + case GL_BITMAP_TOKEN: + loc += 7; + // nprimitives++; + break; + default: + /* XXX Left as an excersie to the reader. */ + printf("Incomplete implementation 2. Unexpected token (%d).\n", + token); + exit(1); + } + } + + /* Allocate an array of pointers that will point back at + primitives in the feedback buffer. There will be one + entry per primitive. This array is also where we keep the + primitive's average depth. There is one entry per + primitive in the feedback buffer. */ + prims = (DepthIndex *) malloc(sizeof(DepthIndex) * nprimitives); + + item = 0; + loc = buffer; + while (loc < end) { + prims[item].ptr = loc; /* Save this primitive's location. */ + token = (int) *loc; + loc++; + switch (token) { + case GL_LINE_TOKEN: + case GL_LINE_RESET_TOKEN: + vertex = (Feedback3Dcolor *) loc; + depthSum = vertex[0].z + vertex[1].z-0.00009; //A small constant keeps polygon offset + prims[item].depth = depthSum / 2.0; + prims[item].width = width/2; + loc += 14; + break; + case GL_POLYGON_TOKEN: + nvertices = (int) *loc; + loc++; + vertex = (Feedback3Dcolor *) loc; + depthSum = vertex[0].z; + for (i = 1; i < nvertices; i++) { + depthSum += vertex[i].z; + } + prims[item].depth = depthSum / nvertices; + loc += (7 * nvertices); + break; + case GL_POINT_TOKEN: + vertex = (Feedback3Dcolor *) loc; + prims[item].depth = vertex[0].z; + loc += 7; + break; + case GL_PASS_THROUGH_TOKEN: + #ifdef DEBUG + printf("Got passthrough token: %c\n",(char)*loc); + #endif + switch ((char)*loc) { //process pass through parameters: + case 'L': + loc+=2; + width=*(loc); + #ifdef DEBUG + printf("width = %f",width); + #endif + break; + }; + fflush(stdout); + loc += 1; + item--; + break; + case GL_BITMAP_TOKEN: + //Ignore bitmaps for now: + #ifdef DEBUG + printf("Cant do Text characters yet!!! Character dropped\n"); + fflush(stdout); + #endif + loc += 7; + item--; + break; + default: + /* XXX Left as an excersie to the reader. */ + assert(1); + } + item++; + } + assert(item == nprimitives); + + /* Sort the primitives back to front. */ + qsort(prims, nprimitives, sizeof(DepthIndex), compare); + + /* Understand that sorting by a primitives average depth + doesn't allow us to disambiguate some cases like self + intersecting polygons. Handling these cases would require + breaking up the primitives. That's too involved for this + example. Sorting by depth is good enough for lots of + applications. */ + + /* Emit the Encapsulated PostScript for the primitives in + back to front order. */ + for (item = 0; item < nprimitives; item++) { + (void) spewPrimitiveEPS(file, prims[item]); + } + + free(prims); + } + + #define EPS_GOURAUD_THRESHOLD 0.05 /* Lower for better (slower) + + smooth shading. */ + + void + spewWireFrameEPS(FILE * file, int doSort, GLint size, GLfloat * buffer, char *creator) + { + GLfloat clearColor[4], viewport[4]; + GLfloat lineWidth; + int i; + + /* Read back a bunch of OpenGL state to help make the EPS + consistent with the OpenGL clear color, line width, point + size, and viewport. */ + glGetFloatv(GL_VIEWPORT, viewport); + glGetFloatv(GL_COLOR_CLEAR_VALUE, clearColor); + glGetFloatv(GL_LINE_WIDTH, &lineWidth); + glGetFloatv(GL_POINT_SIZE, &pointSize); + + /* Emit EPS header. */ + fputs("%!PS-Adobe-2.0 EPSF-2.0\n", file); + /* Notice %% for a single % in the fprintf calls. */ + fprintf(file, "%%%%Creator: %s (using OpenGL feedback)\n", creator); + fprintf(file, "%%%%BoundingBox: %g %g %g %g\n", + viewport[0], viewport[1], viewport[2], viewport[3]); + fputs("%%EndComments\n", file); + fputs("\n", file); + fputs("gsave\n", file); + fputs("\n", file); + + /* Output Frederic Delhoume's "gouraudtriangle" PostScript + fragment. */ + fputs("% the gouraudtriangle PostScript fragement below is free\n", file); + fputs("% written by Frederic Delhoume (delhoume@ilog.fr)\n", file); + fprintf(file, "/threshold %g def\n", EPS_GOURAUD_THRESHOLD); + for (i = 0; gouraudtriangleEPS[i]; i++) { + fprintf(file, "%s\n", gouraudtriangleEPS[i]); + } + + fprintf(file, "\n%g setlinewidth\n", lineWidth); + + /* Clear the background like OpenGL had it. */ + fprintf(file, "%g %g %g setrgbcolor\n", + clearColor[0], clearColor[1], clearColor[2]); + fprintf(file, "%g %g %g %g rectfill\n\n", + viewport[0], viewport[1], viewport[2], viewport[3]); + + spewSortedFeedback(file, size, buffer); + + /* Emit EPS trailer. */ + fputs("grestore\n\n", file); + fputs("%Add `showpage' to the end of this file to be able to print to a printer.\n", + file); + + fclose(file); + } + + void + outputEPS(int size, int doSort, char *filename) + { + GLfloat *feedbackBuffer; + GLint returned; + FILE *file; + + feedbackBuffer = (GLfloat*) calloc(size, sizeof(GLfloat)); + glFeedbackBuffer(size, GL_3D_COLOR, feedbackBuffer); + (void) glRenderMode(GL_FEEDBACK); + render(); + returned = glRenderMode(GL_RENDER); + if (filename) { + file = fopen(filename, "w"); + if (file) { + spewWireFrameEPS(file, doSort, returned, feedbackBuffer, "Gnuplot"); + } else { + printf("Could not open %s\n", filename); + } + }; + /* Helps debugging to be able to see the decode feedback + buffer as text. */ + // printBuffer(returned, feedbackBuffer); + free(feedbackBuffer); + } + Only in gnuplot-opengl_work/src/opengl: gl2ps.c~ Only in gnuplot-opengl_work/src/opengl: gl2ps.o diff -rc gnuplot-3.8b/src/opengl/gnuplot_opengl.c gnuplot-opengl_work/src/opengl/gnuplot_opengl.c *** gnuplot-3.8b/src/opengl/gnuplot_opengl.c Sat Jan 22 22:20:01 2000 --- gnuplot-opengl_work/src/opengl/gnuplot_opengl.c Sat Jan 22 21:23:25 2000 *************** *** 0 **** --- 1,1243 ---- + #include "GL/glut.h" + #include + #include + #include + #include + #include + #include + #include + #define PI 3.1415 + + //A vector class. + class vector + { + public: + GLfloat x,y,z; + vector operator/(const GLfloat &) const; + vector operator*(const GLfloat &) const; + double operator*(const vector &) const; + vector operator/(const vector &) const; + vector operator+(const vector &) const; + vector operator-(const vector &) const; + vector& operator=(const vector &); + // operator GLfloat(); + void display(vector &); + private: + + }; + + void + display (vector &v) + { + printf("(%f,%f,%f)",v.x,v.y,v.z); + }; + + inline vector operator*(const GLfloat &x,const vector &v) + { + vector ans; + ans.x=v.x*x; + ans.y=v.y*x; + ans.z=v.z*x; + return(ans); + }; + + inline vector& vector::operator=(const vector &rhs) + { + this->x=rhs.x; + this->y=rhs.y; + this->z=rhs.z; + return *this; + }; + + inline vector vector::operator*(const GLfloat &mag) const + { + vector out; + out.x=this->x*mag; + out.y=this->y*mag; + out.z=this->z*mag; + return out; + }; + + inline vector vector::operator/(const GLfloat &mag) const + { + vector out; + out.x=this->x/mag; + out.y=this->y/mag; + out.z=this->z/mag; + return out; + }; + + inline double vector::operator*(const vector &v) const + //Two vectors multiplied are the dot product, and yield a double + { + vector out; + out.x=this->x*v.x; + out.y=this->y*v.y; + out.z=this->z*v.z; + return out.x+out.y+out.z; + }; + + inline vector vector::operator+(const vector &v) const + { + vector out; + out.x=this->x+v.x; + out.y=this->y+v.y; + out.z=this->z+v.z; + return out; + }; + + inline vector vector::operator-(const vector &v) const + { + vector out; + out.x=this->x-v.x; + out.y=this->y-v.y; + out.z=this->z-v.z; + return out; + }; + + inline vector vector::operator/(const vector &v) const + { + GLfloat mag=sqrt(v.x*v.x+v.y*v.y+v.z*v.z); + vector out; + out.x=this->x/mag; + out.y=this->y/mag; + out.z=this->z/mag; + return out; + }; + + vector cross(const vector& r,const vector& v) + { + vector u; + u.x=(r.y*v.z-r.z*v.y); + u.y=-(r.x*v.z-r.z*v.x); + u.z=(r.x*v.y-r.y*v.x); + return(u); + }; + + //Function prototypes: + static int SizeofString(void *font, char *string); + static void DrawBitmapString(void *font, char *string); + struct rgb color_map(float z,int colormap,char *i) ; + void display(void); + void render(void); + void init (void) ; + float fps(void); + void mouse_click (int button, int state, int x, int y); + void mouse_move (int x, int y); + struct opengl_command *add_command(); + void display_command(struct opengl_command * x); + void clear_commands(void); + void menu_file(int which); + void keyboard (unsigned char key,int x,int y); + void keyboard_special(int key,int x,int y); + int check_buffered_input(); + char add_points(vector a,int colormap); + void create_poly(vector a, vector b,vector c,int colormap); + void process_input(void); + void check_inputs(int x); + + //Stuff supplied by gl2ps + extern void outputEPS(int size, int doSort, char *filename); + + GLfloat display_width,display_height; // State variables of display dimensions + GLfloat left_obj=-0.6,right_obj=0.6,top_obj=0.6,bottom_obj=-0.6; //current viewing volume in object coordinates. + GLfloat left_fix=-0.6,right_fix=0.6,top_fix=0.6,bottom_fix=-0.6; //current viewing volume in fixed coordinates. + vector r={0,0,1}; //Viewpoint vector + vector u={0,1,0}; //Up vector + vector v=cross(r,u); //Cross product of U x R + vector origin={0,0,0}; //origin of object + int x_old,y_old; //Remembers last coordinates of mouse events + int left_click_state=0; //State variable for left mouse click + int middle_click_state=0; //State variable for middle mouse click + int shift_pressed=0; //State variable for middle mouse click + int light=0; + void *font=GLUT_BITMAP_HELVETICA_12; + int keyboard_rate=10; //rate of change of position from keyboard + long stack_size = 1; + + //The following structure is needed because the coordinates need to be + //prescanned for incresed speed at redrawing. + struct opengl_command { + char operation; //Type of operation (move,line,polygon etc) + float x,y,z; // Prescanned coordinates. + char *text; // For text objects + struct opengl_command *next; //linked list + } plot; + + struct opengl_command *last=&plot; // must always point to end of list + + struct rgb { + float red; + float green; + float blue; + }; + + char justify; //state variable for text justification + struct light { + float x,y,z; //position and strength + } lights[]={ //initialize array to get default values. + {0,0,0}, //ambient + {1,1,1}, //Diffusive + {1,1,1}, //specular + {0,0,0}, //position + {0,0,0}, {1,1,1}, {1,1,1}, {0,0,0}, + {0,0,0}, {1,1,1}, {1,1,1}, {0,0,0}, + {0,0,0}, {1,1,1}, {1,1,1}, {0,0,0}, + {0,0,0}, {1,1,1}, {1,1,1}, {0,0,0}, + {0,0,0}, {1,1,1}, {1,1,1}, {0,0,0}, + {0,0,0}, {1,1,1}, {1,1,1}, {0,0,0}, + {0,0,0}, {1,1,1}, {1,1,1}, {0,0,0}, + }; //opengl has a maximum of 8 simultaneous light sources. + + char lights_count=0; //total number of directional lights in use + + struct line_type { + //A line type is defined by these characteristics (this table is not used for + //polygonal surfaces- linetype has a different meanning then. + float width; + int bytes; //number of bytes of stipple + int stipple; + struct rgb color; + } lt_table[]={ //Note that there must be exactly as many line types as surface types!!! + {2,0,0xFF,{1,1,1}}, //border + {1,1,0x0303,{1,1,1}}, //Tick marks. + {1,0,0xFF,{1,1,1}}, + {1,0,0xFF,{1,0,0}}, + {1,0,0xFF,{0,1,0}}, + {1,0,0xFF,{0,0,1}}, + {1,0,0xFF,{1,0,1}}, + {1,0,0xFF,{0.8,0.8,1}}, + {1,0,0xFF,{1,1,0}}, + {1,0,0xFF,{1,0.8,0.8}}, + {1,0,0xFF,{0.8,1,0.8}}, + {1,3,0xAAAA,{1,1,1}}, + {1,2,0x0C0F,{1,1,1}}, + {1,0,0xFF,{0,0,0}}}; + + #define LINE_TYPES 13 //Number of distinct line types. + // Note that the last element must be of color {0,0,0} as its being used for + // hidden line removal. It is not selectable by the user. + // If you add more linetypes make sure you adjust the corresponding value in + // plotopengl_hiddenlines in graph3d.c + + int linetype=0; // current linetype. + + #define SURF_TYPE_SIZE 6 //numnber of allowed rgb points + #define MINZ -0.166 + #define MAXZ 0.5 + #define RANGE (MAXZ-MINZ) + + struct color_point { + //a surface uses the lt to specify a color scheme for z coloring. + float z; //z height [-0.5,0.5] + struct rgb color; //color for that position + } st1[]={ //Note each line has to have exactly SURF_TYPE_SIZE elements, + //and there should be exactly LINE_TYPES lines here!!! + {-0.5,{1,1,1}},{0.5,{1,1,1}},{0.5,{1,1,1}},{0.5,{1,1,1}},{0.5,{1,1,1}},{0.5,{1,1,1}}, //white + {-0.5,{1,1,1}},{0.5,{1,1,1}},{0.5,{1,1,1}},{0.5,{1,1,1}},{0.5,{1,1,1}},{0.5,{1,1,1}}, //" + {-0.5,{1,1,1}},{0.5,{1,1,1}},{0.5,{1,1,1}},{0.5,{1,1,1}},{0.5,{1,1,1}},{0.5,{1,1,1}}, //" + {-0.5,{1,0,0}},{0.5,{1,0,0}},{0.5,{1,0,0}},{0.5,{1,0,0}},{0.5,{1,1,1}},{0.5,{1,1,1}}, //Red + {-0.5,{0,1,0}},{0.5,{0,1,0}},{0.5,{0,1,0}},{0.5,{0,1,0}},{0.5,{1,1,1}},{0.5,{1,1,1}}, //Green + {-0.5,{0,0,1}},{0.5,{0,0,1}},{0.5,{0,0,1}},{0.5,{0,0,1}},{0.5,{1,1,1}},{0.5,{1,1,1}}, //Blue + {MINZ,{1,0,0}},{MINZ+RANGE/5,{1,1,0}},{MINZ+2*RANGE/5,{0,1,0}},{MINZ+3*RANGE/5,{0,1,1}},{MINZ+4*RANGE/5,{0,0,1}},{MAXZ,{1,0,1}}, // HSV + {MINZ,{0,0,0}},{MINZ+RANGE/3,{1,0,0}},{MINZ+2*RANGE/3,{1,1,0}},{MAXZ,{1,1,1}},{0.5,{1,1,1}},{0.5,{1,1,1}}, // HOT + {MINZ,{0,1,1}},{MAXZ,{1,0,1}},{0.5,{1,1,1}},{0.5,{1,1,1}},{0.5,{1,1,1}},{0.5,{1,1,1}}, //Cool + {MINZ,{0,0,0}},{MINZ+4*RANGE/5,{1,0.6,0.4}},{MAXZ,{1,0.8,0.6}},{0.5,{1,1,1}},{0.5,{1,1,1}},{0.5,{1,1,1}}, //Copper + {MINZ,{1,0,1}},{MAXZ,{1,1,0}},{0.5,{1,1,1}},{0.5,{1,1,1}},{0.5,{1,1,1}},{0.5,{1,1,1}}, + {MINZ,{1,0,0}},{MAXZ,{1,1,0}},{0.5,{1,1,1}},{0.5,{1,1,1}},{0.5,{1,1,1}},{0.5,{1,1,1}}, + {MINZ,{0,0,1}},{MAXZ,{0,1,0.5}},{0.5,{1,1,1}},{0.5,{1,1,1}},{0.5,{1,1,1}},{0.5,{1,1,1}}, + {MINZ,{0,0,0}},{MAXZ,{0,0,0}},{0.5,{1,1,1}},{0.5,{1,1,1}},{0.5,{1,1,1}},{0.5,{1,1,1}}, //Black surface for hidden3d + }; + + static int SizeofString(void *font, char *string) + { + int i,j=0; + + for (i = 0; string[i]; i++) + j+=glutBitmapWidth(font, string[i]); + return(j); + } + + + static void DrawBitmapString(void *font, char *string) + { + int i; + + for (i = 0; string[i]; i++) + glutBitmapCharacter(font, string[i]); + } + + /* + static void DrawStrokeString(void *font, char *string) + { + int i; + + for (i = 0; string[i]; i++) + glutStrokeCharacter(font, string[i]); + } + */ + + struct rgb + color_map(float z,int colormap,char *i) //z in [-0.5,0.5] colormap is the surface type to use + { + struct rgb ans; + float a; + + for((*i)=0;(*i)operation,gluErrorString(errorcode)); + if(tmp->next) + tmp=tmp->next; //Thou shall not follow the NULL pointer + switch (tmp->operation) + { + case 'F': { //Switch to fixed coordinate system: + glEnd(); + glPushMatrix(); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + //The following is needed to reset to a constant + //coordinate system and view point. Because text + //placement relies on left_obj etc, they must also be + //set. The real values can be restored later. + left_fix=left_obj;right_fix=right_obj;top_fix=top_obj;bottom_fix=bottom_obj; + left_obj=-0.6,right_obj=0.6,top_obj=0.6,bottom_obj=-0.6; + glOrtho(left_obj,right_obj,bottom_obj,top_obj, -500, 500); + glBegin(GL_LINE_STRIP); + break; + }; + case 'f': { //Switch back + glEnd(); + glPopMatrix(); + left_obj=left_fix;right_obj=right_fix;top_obj=top_fix;bottom_obj=bottom_fix; + glBegin(GL_LINE_STRIP); + break; + }; + case 'm': + case 'M': { + glEnd(); + glBegin(GL_LINE_STRIP); + glVertex3f(tmp->x,tmp->y,tmp->z); + break; + }; + case 'v': + case 'V': { + glVertex3f(tmp->x,tmp->y,tmp->z); + break; + }; + case 'J': { + justify=(int)tmp->x; + break; + }; + case 't': + case 'T': { + float vertical=tmp->y-glutBitmapWidth(font,'-')/2/display_height; + float horizontal=(float)SizeofString(font,tmp->text)/display_width*(right_obj-left_obj); + glEnd(); + glPushMatrix(); + switch (justify) { + case 1: {//Centered + glRasterPos3f(tmp->x-horizontal/2.0,vertical,tmp->z); + break; + }; + case 2: {//Right justified + glRasterPos3f(tmp->x-horizontal,vertical,tmp->z); + break; + }; + default:{//left justified + glRasterPos3f(tmp->x,vertical,tmp->z); + break; + }; + }; + DrawBitmapString(font,tmp->text); + glPassThrough((GLfloat)'t'); + glPopMatrix(); + glBegin(GL_LINE_STRIP); + break; + }; + case 'W': { + glLineWidth(tmp->x); + break; + }; + case 'L': {//Load up a new line type + glEnd(); //need to finish off this current line first + glLineWidth(lt_table[(int)tmp->x].width); + glPassThrough((float)'L'); + glPassThrough(lt_table[(int)tmp->x].width); + //FIXME: Is this really necessary? can we come up with a stipple pattern + //for a solid line? + if(lt_table[(int)tmp->x].bytes) + { + glEnable(GL_LINE_STIPPLE); + glLineStipple(lt_table[(int)tmp->x].bytes,lt_table[(int)tmp->x].stipple); + } else glDisable(GL_LINE_STIPPLE); + glColor3f(lt_table[(int)tmp->x].color.red,lt_table[(int)tmp->x].color.green,lt_table[(int)tmp->x].color.blue); + linetype=(int)tmp->x; + glBegin(GL_LINE_STRIP); + break; + }; + case 'N': break; //noop function. + case 'O': { + glEnd(); + if(lights_count) glEnable(GL_LIGHTING); + if(tmp->next->x>0) glFrontFace(GL_CW); //read ahead to establish orientation + else glFrontFace(GL_CCW); + glBegin(GL_TRIANGLE_STRIP); + glNormal3f(tmp->x,tmp->y,tmp->z); + tmp=tmp->next; + while(tmp->next && tmp->next->operation=='O'){ + tmp=tmp->next; + glColor3f(tmp->x,tmp->y,tmp->z); + tmp=tmp->next; + glVertex3f(tmp->x,tmp->y,tmp->z); + }; + glEnd(); + glDisable(GL_LIGHTING); + glBegin(GL_LINE_STRIP); + break; + }; + + }; + } while(tmp->next!=NULL); + }; + glEnd(); + glFlush (); + } + void + init (void) + { + GLfloat specular [] = { .0, .0, .0, 1.0 }; + GLfloat shininess [] = { 100.0 }; + /* select clearing color */ + glClearColor (0.0, 0.0, 0.0, 0.0); + // Set the shading model + glShadeModel(GL_SMOOTH); + + // Set the polygon mode to fill + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + // glPolygonMode(GL_FRONT, GL_FILL); + // glPolygonMode(GL_BACK, GL_LINE); + + // Enable depth testing for hidden line removal + glEnable(GL_DEPTH_TEST); + + // Enable polygon offset to eliminate stitching when drawing surfaces and + // lines together. + glEnable(GL_POLYGON_OFFSET_FILL); + // glPolygonOffset(0.5,0.5); + glPolygonOffset(1,1.5); + + // Define material properties of specular color and degree of + // shininess. + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular); + glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, shininess); + + // Set the GL_AMBIENT_AND_DIFFUSE color state variable to be the + // one referred to by all following calls to glColor + glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); + glEnable(GL_COLOR_MATERIAL); + + plot.operation='N'; //Noop for the first item in list + plot.next=NULL; //initialize the opengl stack. + } + + void + window_reshape (GLint w,GLint h) + { + glViewport(0, 0, w, h); + display_width=(GLfloat)w; display_height=(GLfloat)h; + display(); + }; + + float fps() + { //calculates the frame rate + timeval time1,time2; + float tmp; + + gettimeofday(&time1,NULL); + display(); + gettimeofday(&time2,NULL); + tmp=(float)(time2.tv_usec-time1.tv_usec)*1e-6+(float)(time2.tv_sec-time1.tv_sec); //time taken + //Only do the next bit if it wont take too long... This just improves the + //accuracy for the fps figure + if(tmp<0.1) { + gettimeofday(&time1,NULL); + for(int i=0;i<30;i++) + display(); + gettimeofday(&time2,NULL); + tmp=((float)(time2.tv_usec-time1.tv_usec)*1e-6+(float)(time2.tv_sec-time1.tv_sec))/30; //time taken + } + return(1/tmp); + }; + + + + void + mouse_click (int button, int state, int x, int y) + // grabs mouse click events. + { + if(button==GLUT_LEFT_BUTTON && state==GLUT_DOWN && glutGetModifiers()==GLUT_ACTIVE_SHIFT) + { + left_click_state=1; + shift_pressed=1; + } + if(button==GLUT_LEFT_BUTTON && state==GLUT_UP && shift_pressed) + { + left_click_state=0; + shift_pressed=0; + } + if(button==GLUT_LEFT_BUTTON && state==GLUT_DOWN && !glutGetModifiers()) + { + left_click_state=1; + glutSetCursor(GLUT_CURSOR_CYCLE); + } + if(button==GLUT_LEFT_BUTTON && state==GLUT_UP && !glutGetModifiers()) + { + left_click_state=0; + glutSetCursor(GLUT_CURSOR_INHERIT); + } + //Lets be friendly towards users of inferior OS's that do not understand middle + //button. + if(button==GLUT_LEFT_BUTTON && state==GLUT_DOWN && glutGetModifiers()==GLUT_ACTIVE_CTRL) + { + middle_click_state=1; + glutSetCursor(GLUT_CURSOR_UP_DOWN); + } + if(button==GLUT_LEFT_BUTTON && state==GLUT_UP && middle_click_state) + { + middle_click_state=0; + glutSetCursor(GLUT_CURSOR_INHERIT); + } + if(button==GLUT_MIDDLE_BUTTON && state==GLUT_DOWN) + { + middle_click_state=1; + glutSetCursor(GLUT_CURSOR_UP_DOWN); + }; + if(button==GLUT_MIDDLE_BUTTON && state==GLUT_UP) + { + middle_click_state=0; + glutSetCursor(GLUT_CURSOR_INHERIT); + }; + + x_old=x; y_old=y; + }; + + inline GLfloat mag(vector r) + { + return(sqrt(r.x*r.x+r.y*r.y+r.z*r.z)); + }; + + #define DAMPER 0.05 //This defines the mouse reponsivity + + void + mouse_move (int x, int y) + { + + if(left_click_state && !shift_pressed ) + { + GLfloat h_2=display_height/2; + GLfloat w_2=display_width/2; + vector rot; // relative amount for viewport rotations + vector rnew; // Temporary vector + + //Here we try to emulate the trackball feel... + rot.z=-(GLfloat)(x-x_old)*(y-h_2)/(2*h_2)+(GLfloat)(y-y_old)*(x-w_2)/(2*w_2); + rot.x=(GLfloat)(x-x_old)*sqrt(fabs(h_2*h_2-(y-h_2)*(y-h_2)))/(2*h_2); + rot.y=(GLfloat)(y-y_old)*sqrt(fabs(w_2*w_2-(x-w_2)*(x-w_2)))/(2*w_2); + + if(rot.x) + { + //Now calculates the new R; + rnew=r+(DAMPER*rot.x*v); + //normalize it: + rnew=rnew/rnew; + // Find the new v vector: + v=(rnew-r)*rot.x; + // Normalize it + v=v/v; + //Set new r vector: + r=rnew; + //Calculate the new u vector: + u=cross(v,r); + }; + + if(rot.z) + { + //Find new u vector + u=u+DAMPER*v*rot.z; + //normalize it: + u=u/u; + //Calculate the new value of the v vector + v=cross(r,u); + }; + + if(rot.y) + { + //Now calculates the new R; + rnew=r+DAMPER*u*rot.y; + //normalize it: + rnew=rnew/rnew; + // Find the new u vector: + u=(rnew-r)*rot.y; + //normalize it + u=u/u; + //Set new r vector: + r=rnew; + //Calculate the new v vector: + v=cross(r,u); + }; + }; + + if(middle_click_state) + { + GLfloat delta=(GLfloat)(y-y_old)/10; + GLfloat xbound=fabs(right_obj-left_obj); + GLfloat ybound=fabs(top_obj-bottom_obj); + + //Need to clamp rate of change of size so we dont get delta+1 <0 + //for example + if(delta<-0.5) delta=-0.5; + if(delta>0.5) delta=0.5; + + if((delta>0 && xbound<100 && ybound<100) || (delta<0 && xbound>0.01 + && ybound>0.01)) + { + left_obj*=delta/5+1; + right_obj*=delta/5+1; + bottom_obj*=delta/5+1; + top_obj*=delta/5+1; + }; + }; + if(left_click_state && shift_pressed) + { + //Right mouse button drags the viewport around. + GLfloat deltay=(GLfloat)(y-y_old)/500*(right_obj-left_obj); + GLfloat deltax=(GLfloat)(x-x_old)/500*(right_obj-left_obj); + + left_obj-=deltax; + right_obj-=deltax; + bottom_obj+=deltay; + top_obj+=deltay; + }; + + x_old=x; y_old=y; + glutPostRedisplay(); + }; + + struct opengl_command *add_command() + { + last->next=(struct opengl_command*)malloc(sizeof(plot)); + last=last->next; + last->next=NULL; + stack_size++; + return(last); + }; + + void display_command(struct opengl_command * x) + { + printf("operation is %c, coordinates %f,%f,%f\n",x->operation,x->x,x->y,x->z); + fflush(stdout); + }; + + void clear_commands(void) + { //returns all memory in the linked list back to system. + struct opengl_command *tmp; + + tmp=&plot; + while(tmp->next!=NULL) + { + while(tmp->next->next!=NULL) tmp=tmp->next; //item before last + free(tmp->next->text); //relinquish string + free(tmp->next); + tmp->next=NULL; + tmp=&plot; + last=&plot; + plot.next=NULL; + stack_size=1; + }; + }; + + #define STDIN_TIME 300 //time to wait before checking STDIN for input + + void + menu_file(int which) + {//handles calls for menu + switch(which){ + case 0: + outputEPS(stack_size*8,1,"render.eps"); //We allocate more memory + //than what we will need. Opengl feedback supplies 7 floats per + //vertex. Stacksize is an indication of how many vertices we have + printf("Stack size is: %ld, Just saved render.eps\n",stack_size); + fflush(stdout); + break; + case 1: + keyboard('c',0,0); + break; + case 2: + keyboard('v',0,0); + break; + case 3: + keyboard('?',0,0); + break; + case 4: + exit(0); + break; + + default: break; + + }; + }; + + void + keyboard (unsigned char key,int x,int y) + { + switch(key){ + case 'q':{ + exit(0); + break; + }; + case 'c':{ + r.x=0;r.y=0,r.z=1; + u.x=0;u.y=1,u.z=0; + v=cross(r,u); + left_obj=-0.6,right_obj=0.6,top_obj=0.6,bottom_obj=-0.6; + break; + }; + case 'v':{ //calculate an up vector that aligns the z axis of the graph with + // y axis of display (As is normal in gnuplot). + vector z={0,0,1}; + float a=(r*z)/(r*r); + u=z-a*r; + v=cross(r,u); + break; + }; + case '?':{ //print info + printf("\nposition vector is "); + display(r); + printf("\nup vector is "); + display(u); + printf("\n"); + printf("Frames per seconds are: %f \n ",fps()); + fflush(stdout); + break; + }; + case '+':{ + if(glutGetModifiers()==GLUT_ACTIVE_SHIFT) { + middle_click_state=1; + y_old=y; + y=y-keyboard_rate; + mouse_move(0,y); + middle_click_state=0; + } + else if(keyboard_rate<100) keyboard_rate++; + break; + }; + case '-':{ + if(glutGetModifiers()==GLUT_ACTIVE_SHIFT) { + middle_click_state=1; + y_old=y; + y=y+keyboard_rate; + mouse_move(0,y); + middle_click_state=0; + } + if(keyboard_rate>2) keyboard_rate--; + break; + }; + + }; + glutPostRedisplay(); + } + void + keyboard_special(int key,int x,int y) + //takes care of keyboard navigation + { + switch(key){ + case GLUT_KEY_LEFT: if(glutGetModifiers()==GLUT_ACTIVE_SHIFT) + shift_pressed=1; //shift + arrows causes a translation; + else left_click_state=1; + x_old=x;y_old=(int)display_height/2; + x=x-keyboard_rate; + mouse_move(x,y_old); + left_click_state=0; + shift_pressed=0; + break; + case GLUT_KEY_RIGHT: if(glutGetModifiers()==GLUT_ACTIVE_SHIFT) + shift_pressed=1; //shift + arrows causes a translation; + else left_click_state=1; + x_old=x;y_old=(int)display_height/2; + x=x+keyboard_rate; + mouse_move(x,y_old); + left_click_state=0; + shift_pressed=0; + break; + case GLUT_KEY_UP: if(glutGetModifiers()==GLUT_ACTIVE_SHIFT) + shift_pressed=1; //shift + arrows causes a translation; + else left_click_state=1; + x_old=(int)display_width/2;y_old=y; + y=y-keyboard_rate; + mouse_move(x_old,y); + left_click_state=0; + shift_pressed=0; + break; + case GLUT_KEY_DOWN: if(glutGetModifiers()==GLUT_ACTIVE_SHIFT) + shift_pressed=1; //shift + arrows causes a translation; + else left_click_state=1; + x_old=(int)display_width/2;y_old=y; + y=y+keyboard_rate; + mouse_move(x_old,y); + left_click_state=0; + shift_pressed=0; + break; + case GLUT_KEY_HOME: left_click_state=1; + x_old=x;y_old=0; + x=x-keyboard_rate; + mouse_move(x,0); + left_click_state=0; + break; + case GLUT_KEY_PAGE_UP: left_click_state=1; + x_old=x;y_old=0; + x=x+keyboard_rate; + mouse_move(x,0); + left_click_state=0; + break; + }; + }; + + int + check_buffered_input() + { + struct timeval timeout; + timeout.tv_sec =0; + timeout.tv_usec =0; //Do not wait + fd_set tset; + + FD_ZERO(&tset); + FD_SET(fileno(stdin), &tset); //watch stdin for input + return( select(1,&tset,NULL,NULL,&timeout)); //zero if nothing there. + }; + + inline float + max(float a,float b) + { + return(a>b?a:b); + }; + inline float + min(float a,float b) + { + return(ax=ans.red;tmp->y=ans.green;tmp->z=ans.blue; + tmp->operation='O'; + + tmp=add_command(); + tmp->x=a.x;tmp->y=a.y;tmp->z=a.z; + tmp->operation='O'; + return(i); + }; + + void + create_poly(vector a, vector b,vector c,int colormap) + //This function breaks the triangles given by the vertices above into a polygon for + //display() to draw. Points are added to the triangle at z positions which + //have a color change in them, to properly implement the colormaps. + { + struct opengl_command *tmp; + vector tmp_vector; + char i; + char direction=1; //This keeps track of our surface normals, Each time we + //swap vectors we change orientation of the triangle + + if(a.z>b.z) { + tmp_vector=a; + a=b; + b=tmp_vector; + direction*=-1; + }; + if(b.z>c.z) { + tmp_vector=b; + b=c; + c=tmp_vector; + direction*=-1; + }; + if(a.z>b.z) { + tmp_vector=a; + a=b; + b=tmp_vector; + direction*=-1; + }; + + //Save orientation into stack: + tmp=add_command(); + tmp->x = direction; + tmp->operation='O'; + + //Now we have a is lowest point,b is middle and c is top. + i=add_points(a,colormap); + //Now search a->b to find all colormap crossings + while(st1[i+colormap*SURF_TYPE_SIZE].z>a.z && + st1[i+colormap*SURF_TYPE_SIZE].zmin(b.z,c.z) && + st1[i+colormap*SURF_TYPE_SIZE].z=0) length+=err; + else { fprintf(stderr,"Could not read stdin?\n"); + exit(-1); + }; + //This is a hack to exit if gnuplot crashes + if(!err && check_buffered_input()) + { + fprintf(stderr,"Broken pipe. Terminating\n"); + exit(-1); + }; + + if(length>0) buffer[length-1]=rd_buf; + } while(rd_buf!='\n' && err>0); + buffer[length]=0; + rd_buf='a'; + + switch(buffer[0]) + { + case 'R': { + #ifdef DEBUG + printf("exiting"); + #endif + exit(0); + break; + }; + case 'F': { //Switch to fixed coordinate system + tmp=add_command(); + tmp->operation=buffer[0]; + break; + }; + case 'f': { //Switch from fixed coordinate system + tmp=add_command(); + tmp->operation=buffer[0]; + break; + }; + case 'M': + case 'V': { + tmp=add_command(); + stack_size++; //every line has 2 vertices + sscanf(buffer+1,"%f,%f",&tmp->x,&tmp->y); + tmp->z=0; + if(!isinf(tmp->x) &&!isinf(tmp->y) &&!isinf(tmp->z) ) + tmp->operation=buffer[0]; + else + tmp->operation='N'; //Forget about it + #ifdef DEBUG + display_command(tmp); + #endif + break; + }; + case 'm': + case 'v': { + tmp=add_command(); + stack_size++; //every line has 2 vertices + sscanf(buffer+1,"%f,%f,%f",&tmp->x,&tmp->y,&tmp->z); + if(finite(tmp->x) && finite(tmp->y) && finite(tmp->z)) + tmp->operation=buffer[0]; + else + tmp->operation='N'; //Forget about it + #ifdef DEBUG + if(isinf(tmp->x) ||isinf(tmp->y) ||isinf(tmp->z) ) + display_command(tmp); + #endif + break; + }; + case 'L': { //Line type + div_t divide; + tmp=add_command(); + sscanf(buffer+1,"%f",&tmp->x); + divide = div((int)tmp->x+2,LINE_TYPES); + tmp->x = (float) divide.rem; + tmp->operation=buffer[0]; + linetype=(int)tmp->x; + #ifdef DEBUG + printf("line type set to %f\n", tmp->x); + fflush(stdin); + #endif + break; + }; + case 'K': { //Light sources and other options. + if(lights_count<8){ + switch(buffer[1]){ + case 'A': + { //ambient directive + if(sscanf(buffer+2,"%f,%f,%f",&(lights[lights_count*4].x),&lights[lights_count*4].y,&lights[lights_count*4].z)!=3) printf("Could not read %s\n",buffer+2); + break; + }; + case 'D': + { //diffuse directive + if(sscanf(buffer+2,"%f,%f,%f",&(lights[lights_count*4+1].x),&lights[lights_count*4+1].y,&lights[lights_count*4+1].z)!=3) printf("Could not read %s\n",buffer+2); + break; + }; + case 'S': + { //specular directive + if(sscanf(buffer+2,"%f,%f,%f",&(lights[lights_count*4+2].x),&lights[lights_count*4+2].y,&lights[lights_count*4+2].z)!=3) printf("Could not read %s\n",buffer+2); + break; + }; + case 'P':{ //Position of light + if(sscanf(buffer+2,"%f,%f,%f",&(lights[lights_count*4+3].x),&lights[lights_count*4+3].y,&lights[lights_count*4+3].z)!=3) printf("Could not read %s\n",buffer+2); + lights_count++; + break; + }; + case 'W': { //white background + glClearColor(1.0,1.0,1.0,1.0); + for(int i=0;i<3;i++) + { + lt_table[i].color.red=0; + lt_table[i].color.green=0; + lt_table[i].color.blue=0; + }; + for(int i=0;i