/* ** psdraw.c */ #include #include #include "peek.h" /* ** psdraw_surface() ** Assumes that the object has been unedged and oriented, and ** processed so that verts know their screen coords and faces ** know of they're visible. ** ** given a surface and a unitary light vector, draws the surface ** according to the parameters passed. */ int psdraw_surface(FILE *file, Part *surf, Enviro *env, int page, char *text) { static int flip = 0; /* equals 0 or 1 depending if drawing on lower or upper half of the page */ int i, edges; Part *face = NULL, *vert, *vert2; Image *face_im, *vert_im; float *norm = NULL, to_eye[THREE], gray, dot; char err2[ERRSTRLEN]; #ifdef DEBUG printf("psdraw_surface(%d): hi, surf->d = %d\n", surf->ID, surf->d); #endif if (3 < surf->d) { sprintf(err2, "psdraw_surface: can't draw %d-D surface (only <= 3)\n", surf->d); strcat(err, err2); return(-1); } if (3 == surf->d) { /* first shade in the visible faces */ edges = (env->frontwidth) || (env->backwidth); face_im = NULL; if (edges) fprintf(file, "gsave\n"); do { face_im = (!face_im ? surf->thought : face_im->next); face = face_im->sense; #ifdef DEBUG printf("psdraw_surface(%d): testing face %d for shading\n", surf->ID, face->ID); #endif if (face->spare) { #ifdef DEBUG fprintf(file, "%%%% shaded face %d\n", face->ID); printf("psdraw_surface(%d): will shade face %d\n", surf->ID, face->ID); #endif fprintf(file, "newpath\n"); vert_im = NULL; do { vert_im = (!vert_im ? face->thought : vert_im->next); vert = vert_im->sense; #ifdef DEBUG printf("psdraw_surface(%d): vert %d of shaded face %d\n", surf->ID, vert->ID, face->ID); #endif fprintf(file, "%g %g %s\n", flip*612 +(1 -2*flip)*(env->scale*72 * (vert->coord_screen[1]) +180), flip*792 +(1 -2*flip)*(env->scale*72 * (-vert->coord_screen[0])+180), (vert == face->thought->sense ? "moveto" : "lineto")); } while (vert_im->next); fprintf(file, "closepath\n"); norm = face->norm; #ifdef DEBUG printf("psdraw_surface: on face %d:\n", face->ID); printf("norm = %g %g %g\nlight = %g %g %g\n", norm[0], norm[1], norm[2], (env->light)[0], (env->light)[1], (env->light)[2]); #endif gray = norm[0]*(env->light)[0] +norm[1]*(env->light)[1] +norm[2]*(env->light)[2]; gray = env->amb + (1 - env->amb)*(gray + 1)*(gray + 1)*0.25; fprintf(file, "%g setgray fill\n", gray); } } while (face_im->next); if (edges) fprintf(file, "grestore\n"); #ifdef DEBUG printf("psdraw_surface(): done with shaded faces\n"); #endif /* now draw the wire frame on top of the shaded faces */ face_im = NULL; do { face_im = (!face_im ? surf->thought : face_im->next); face = face_im->sense; if ((env->frontwidth && face->spare) || (env->backwidth && !(face->spare))) { /* if we are supposed to draw edges on this kind of face */ #ifdef DEBUG fprintf(file, "%%%% edges of face %d\n", face->ID); #endif fprintf(file, "newpath\n"); vert_im = NULL; do { vert_im = (!vert_im ? face->thought : vert_im->next); vert = vert_im->sense; fprintf(file, "%g %g %s\n", flip*612 + (1 - 2*flip)*(env->scale*72 * (vert->coord_screen[1]) +180), flip*792 + (1 - 2*flip)*(env->scale*72 * (-vert->coord_screen[0])+180), (vert == face->thought->sense ? "moveto" : "lineto")); } while (vert_im->next); fprintf(file, "closepath\n"); fprintf(file, "1 setlinejoin\n"); fprintf(file, "%g setlinewidth\n", ((face->spare) ? env->frontwidth : env->backwidth)); fprintf(file, "stroke\n"); } } while (face_im->next); } else if (2 == surf->d) { #ifdef DEBUG printf("psdraw_surface(%d): drawing single face...\n", surf->ID); #endif /* single face is visible, so draw it */ fprintf(file, "newpath\n"); vert_im = NULL; do { vert_im = (!vert_im ? surf->thought : vert_im->next); vert = vert_im->sense; #ifdef DEBUG printf("psdraw_surface(%d): vert %d of shaded face/surface %d\n", surf->ID, vert->ID, surf->ID); #endif fprintf(file, "%g %g %s\n", flip*612 +(1 -2*flip)*(env->scale*72 * (vert->coord_screen[1]) +180), flip*792 +(1 -2*flip)*(env->scale*72 * (-vert->coord_screen[0])+180), (vert == surf->thought->sense ? "moveto" : "lineto")); } while (vert_im->next); fprintf(file, "closepath\n"); /* to determine how to shade face, check to see if we are on the lit side or the shadow side of the face */ vert = surf->thought->sense; for (i=0; i<=THREE; i++ ) to_eye[i] = env->eye[i] - vert->coord[i]; dot = env->light[0]*to_eye[0] + env->light[1]*to_eye[1] + env->light[2]*to_eye[2]; /* dot > 0 : we're on the lit side; dot < 0 : we're on shadow side */ gray = norm[0]*(env->light)[0] +norm[1]*(env->light)[1] +norm[2]*(env->light)[2]; /* if we're on the shadow side and gray > -gray, then gray represents gray for lit side, so set it to -gray, the gray for the shadow side */ if (dot < 0 && gray > -gray) gray = -gray; gray = env->amb + (1 - env->amb)*(gray + 1)*(gray + 1)*0.25; fprintf(file, "%g setgray fill\n", gray); /* now draw edges for this face */ if (env->frontwidth) { fprintf(file, "newpath\n"); vert_im = NULL; do { vert_im = (!vert_im ? face->thought : vert_im->next); vert = vert_im->sense; fprintf(file, "%g %g %s\n", flip*612 + (1 - 2*flip)*(env->scale*72 * (vert->coord_screen[1]) +180), flip*792 + (1 - 2*flip)*(env->scale*72 * (-vert->coord_screen[0])+180), (vert == face->thought->sense ? "moveto" : "lineto")); } while (vert_im->next); fprintf(file, "closepath\n"); fprintf(file, "1 setlinejoin\n"); fprintf(file, "%g setlinewidth\n", env->frontwidth); fprintf(file, "stroke\n"); } } else if (1 == surf->d) { #ifdef DEBUG printf("psdraw_surface(%d): drawing single edge\n", surf->ID); #endif vert = surf->thought->sense; vert2 = surf->thought->next->sense; fprintf(file, "newpath\n"); fprintf(file, "%g %g moveto\n", flip*612 + (1 - 2*flip)*(env->scale*72 * (vert->coord_screen[1]) +180), flip*792 + (1 - 2*flip)*(env->scale*72 * (-vert->coord_screen[0])+180)); fprintf(file, "%g %g lineto\n", flip*612 + (1 - 2*flip)*(env->scale*72 * (vert2->coord_screen[1]) +180), flip*792 + (1 - 2*flip)*(env->scale*72 * (-vert2->coord_screen[0])+180)); fprintf(file, "1 setlinejoin\n"); fprintf(file, "%g setlinewidth\n", env->frontwidth); fprintf(file, "stroke\n"); } else /* 0 == surf->d */ { #ifdef DEBUG printf("psdraw_surface(%d): drawing single point\n", surf->ID); #endif fprintf(file, "newpath\n"); if (env->frontwidth) { fprintf(file, "%g %g moveto\n", flip*612 + (1 - 2*flip)*(env->scale*72 * (surf->coord_screen[1]) +180), flip*792 + (1 - 2*flip)*(env->scale*72 * (-surf->coord_screen[0])+180)); fprintf(file, "%g %g lineto\n", flip*612 + (1 - 2*flip)*(env->scale*72 * (surf->coord_screen[1]) +180), flip*792 + (1 - 2*flip)*(env->scale*72 * (-surf->coord_screen[0])+180)); fprintf(file, "1 setlinejoin\n"); fprintf(file, "%g setlinewidth\n", env->frontwidth); fprintf(file, "stroke\n"); } } if (text) { fprintf(file, "gsave\n"); fprintf(file, "%d %d translate\n", flip*612 + (1 - 2*flip)*530, flip*792 + (1 - 2*flip)*198); fprintf(file, "%d rotate\n", (2*flip - 1)*90); fprintf(file, "/Times-Roman findfont\n30 scalefont\nsetfont\n0 0 moveto"); fprintf(file, "(%s) show\n", text); fprintf(file, "grestore\n"); } if (flip || page) { fprintf(file, "showpage\n\n"); } if (!page) flip = 1 - flip; return(0); } /* psslice_4d() ** given an object, an initial position matrix, an interframe matrix, ** and the number of frames, writes to given filename the postscript ** file which shows the series of cross-sections of the object as ** manipulated by the given matrices. ** ** NOTE: for time being, only draws first surface of first piece ** (calls psdraw_surface() instead of non-existant psdraw_object() ) */ int psslice_4d(char *filename, Piece *object, Matx *init, Matx *delta, Enviro *env, int frames) { FILE *file, *joe; Piece *cross_object; int i, three; char err2[ERRSTRLEN], text[3]; if (4 != object->space_d) { sprintf(err, "psslice_4d: object must be 4-dimensional (space_d = 4)\n"); return(-1); } file = fopen(filename, "w"); fprintf(file, "%%!\n"); xform(object, init); for (i=1; i<=frames; i++) { cross_object = NULL; if (slice_object(object, &cross_object, ZERO, 0)) { sprintf(err2, "psslice_4d: on frame %d of %d\n", i, frames); strcat(err, err2); return(-1); } if (cross_object) { if (orient_object(cross_object)) { sprintf(err2, "psslice_4d: on frame %d of %d\n", i, frames); strcat(err, err2); return(-1); } if (WtoS_sysI(cross_object, env)) { sprintf(err2, "psslice_4d: on frame %d of %d\n", i, frames); strcat(err, err2); return(-1); } sprintf(text, "%d", i); /* this should really be psdraw_object, but it doesn't exist yet */ if (psdraw_surface(file, cross_object->thought->sense, env, (i == frames ? 1 : 0), text)) { sprintf(err2, "psslice_4d: on frame %d of %d\n", i, frames); strcat(err, err2); return(-1); } dispose_object(cross_object); } xform(object, delta); } fclose (file); return(0); }