/*************************************************************************** * *N point_in_face_table * *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: * * Purpose: *P * Test whether a point is inside a face or not. Must have a valid path- * name to a valid VPF Face file, or else be in graphics mode for the error * message that will result. Filename must have all directory seperators * escapes; eg. c:\\vpf NOT c:\vpf *E *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: * Parameters: *A * x <input> == (float) given point x coordinate. * y <input> == (float) given point y coordinate. * face_id <input> == (rspf_int32) face. * fname <input> == (char *) pathname to VPF face file. * point_in_face_table <output> == VPF_BOOLEAN: * 1 --> point is inside * 0 --> point is not inside *E **************************************************************************/ int point_in_face_table( float x, float y, rspf_int32 face_id, char *fname ) { vpf_table_type facetable, ringtable, edgetable; char *name; int result; name = (char *)vpfmalloc( 255*sizeof(char) ); facetable = vpf_open_table(fname,disk, "rb", NULL ); strupr(fname); strcpy( name, fname ); dirpath( name ); strcat( name, "RNG" ); ringtable = vpf_open_table( name, disk , "rb", NULL ); strcpy( name, fname ); dirpath( name ); strcat( name, "EDG" ); edgetable = vpf_open_table( name, disk , "rb", NULL ); free( name ); result = point_in_face( x, y, face_id, facetable, ringtable, edgetable ); vpf_close_table(&facetable); vpf_close_table(&ringtable); vpf_close_table(&edgetable); return result; }
void slice_sphere (struct msscene *ms, struct surface *current_surface, double fine_pixel, struct face *fac) { int k, j; double yinc, y, rad, fsgn; double cir_center[3], cir_axis[3]; char message[MAXLINE]; struct leaf *lf; struct circle *cir; struct variety *vty; struct cept *ex; vty = fac -> vty; if (vty -> type != SPHERE) { ex = new_cept (ENUM_ERROR, INVALID_VALUE, FATAL_SEVERITY); add_function (ex, "slice_sphere"); add_source (ex, "msrender.c"); add_long (ex, "variety type", (long) vty -> type); return; } /* check versus window */ for (k = 0; k < 3; k++) { if (vty -> center[k] + vty -> radii[0] < ms -> window[0][k]) return; if (vty -> center[k] - vty -> radii[0] > ms -> window[1][k]) return; } /* plus one for convex; minus one for concave */ fsgn = ((fac -> shape == CONVEX) ? 1.0 : -1.0); /* set up circle for leaf */ for (k = 0; k < 3; k++) { cir_center[k] = vty -> center[k]; cir_axis[k] = ((k == 1) ? fsgn : 0.0); } cir = new_circle (cir_center, (double) 0.0, cir_axis); if (cir == NULL) { add_object (tail_cept, CIRCLE, "leaf circle"); add_function (tail_cept, "slice_sphere"); return; } lf = allocate_leaf (); if (lf == NULL) { add_object (tail_cept, LEAF, "leaf"); add_function (tail_cept, "slice_sphere"); return; } /* copy atom number from variety to leaf */ for (j = 0; j < MAXPA; j++) lf -> atmnum[j] = fac -> vty -> atmnum[j]; for (k = 0; k < 3; k++) lf -> focus[k] = vty -> center[k]; /* set up leaf fields */ lf -> cir = cir; lf -> shape = fac -> shape; lf -> type = fac -> vty -> type; lf -> fac = fac; lf -> side = OUTSIDE; lf -> comp = fac -> comp; lf -> input_hue = fac -> input_hue; /* y increment for lines of latitude on sphere */ yinc = fine_pixel; /* one leaf per line of latitude */ for (y = vty -> center[1] - vty -> radii[0] - yinc / 2; y < vty -> center[1] + vty -> radii[0]; y += yinc) { /* change circle center */ cir -> center[1] = y; /* radius of circle of latitude */ rad = (vty -> radii[0] * vty -> radii[0]) - (y - vty -> center[1]) * (y - vty -> center[1]); if (rad <= 0.0) continue; rad = sqrt (rad); if (rad <= 0.0) continue; cir -> radius = rad; /* leaf endpoints: west and east */ for (j = 0; j < 2; j++) for (k = 0; k < 3; k++) lf -> ends[j][k] = cir -> center[k]; lf -> ends[0][0] -= rad; lf -> ends[1][0] += rad; /* determine accessibility of endpoints of leaf */ for (j = 0; j < 2; j++) { lf -> where[j] = point_in_face (lf -> ends[j], fac, 1); if (lf -> where[j] < 0) { ms -> n_bad_projection++; lf -> where[j] = 0; } } /* cut, clip and render (outer) leaf */ lf -> cep = 0; lf -> clip_ep = 0; cut_leaf (ms, current_surface, fine_pixel, lf); if (error()) return; if (current_surface -> clipping) { /* cut, clip and render (inner) leaf */ for (k = 0; k < 3; k++) cir -> axis[k] = ((k == 1) ? -fsgn : 0.0); lf -> cep = 0; lf -> clip_ep = 0; lf -> side = INSIDE; cut_leaf (ms, current_surface, fine_pixel, lf); if (error()) return; /* reset what we changed */ lf -> side = OUTSIDE; for (k = 0; k < 3; k++) cir -> axis[k] = ((k == 1) ? fsgn : 0.0); } } free_leaf (lf); free_circle (cir); return; }
void render_leaf (struct msscene *ms, struct surface *current_surface, double fine_pixel, struct leaf *lf) { int i, k, npoint, x, y, z, shade, hue, atm; int inner, point_clipped, point_if; int shape, comp, input_hue; double input_opacity; double opacity; double norvect[3], horvect[3], pnt[3]; static double *points = (double *) NULL; struct circle *cir; cir = lf -> cir; if (cir -> radius <= 0.0) { ms -> n_missing_leaves++; return; } /* check leaf circle versus window */ for (k = 0; k < 3; k++) { if (cir -> center[k] + cir -> radius < ms -> window[0][k]) return; if (cir -> center[k] - cir -> radius > ms -> window[1][k]) return; } /* subdivide leaf into points (pixels) */ npoint = subdivide_leaf (fine_pixel, lf, &points); if (npoint < 2) { ms -> n_missing_leaves++; return; } /* for each point, compute normal vector, shade, hue */ for (i = 0; i < npoint; i++) { for (k = 0; k < 3; k++) pnt[k] = *(points+3*i+k); for (k = 0; k < 3; k++) norvect[k] = (*(points+3*i+k) - lf -> focus[k]); normalize (norvect); if (lf -> shape != CONVEX) reverse (norvect); /* check every point ? */ if (lf -> cep) { /* check accessibility for problem leaf */ point_if = point_in_face (points + 3 * i, lf -> fac, 1); if (error()) return; if (!point_if) continue; } if (lf -> clip_ep) { /* check clipping for problem leaf */ point_clipped = current_surface -> clipping && clipped (ms, points + 3 * i); if (point_clipped) continue; } inner = 0; /* if no clipping, do not render backward facing pixels */ if (norvect[2] <= 0.0) { if (!(current_surface -> clipping)) continue; /* reverse direction of vector */ inner = 1; for (k = 0; k < 3; k++) norvect[k] *= (-1.0); for (k = 0; k < 3; k++) horvect[k] = norvect[k]; horvect[2] = 0.0; /* move inner side in one & half pixel widths */ for (k = 0; k < 3; k++) *(points+3*i+k) += current_surface -> surface_thickness * ms -> pixel_width * horvect[k]; } /* convert from surface to screen coordinates */ x = ftoi (ms, *(points + 3 * i), 0); y = ftoi (ms, *(points + 3 * i + 1), 1); z = ftoi (ms, *(points + 3 * i + 2), 2); /* closest atom of (1, 2, 3) atoms to point */ atm = closest (current_surface, lf, points + 3 * i); if (error()) return; if (atm <= 0) continue; shape = lf -> shape; if (lf -> type == CYLINDER) shape = 2; if (shape < 1) shape = 1; if (shape > 3) shape = 3; comp = lf -> comp; input_hue = lf -> input_hue; input_opacity = 1 - input_hue % 2; opacity = detopac (atm, inner, comp, shape, current_surface -> scheme, input_opacity); if (error()) return; /* hue from color scheme */ hue = determine_hue (ms -> table, current_surface -> scheme, atm, comp, shape, inner, input_hue, 0.0); if (error()) return; /* get shade (intensity) */ shade = detsh(ms, norvect, z); if (error()) return; /* put pixel into depth buffer */ putpix (ms, current_surface, inner, shade, hue, opacity, x, y, z); if (error()) return; } /* free points of leaf */ free_doubles (points, 0, VERTS); }