/* * $Id: gsd_objs.c,v 2.7 2006/05/05 23:28:59 brad Exp $ */ /* gsd.c Bill Brown, USACERL October 1993 */ #include #include #include #include #include #include "gsget.h" #include "math.h" #include "rowcol.h" /* #define TRACE_DFUNCS */ static void init_stuff(void); /* vertices for octohedron */ float Octo[6][3] = { {1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}, {-1.0, 0.0, 0.0}, {0.0, -1.0, 0.0}, {0.0, 0.0, -1.0} }; #define ONORM .57445626 /* normals for flat-shaded octohedron */ float OctoN[8][3] = { {ONORM, ONORM, ONORM}, {-ONORM, ONORM, ONORM}, {ONORM, -ONORM, ONORM}, {-ONORM, -ONORM, ONORM}, {ONORM, ONORM, -ONORM}, {-ONORM, ONORM, -ONORM}, {ONORM, -ONORM, -ONORM}, {-ONORM, -ONORM, -ONORM}, }; /* ???? not sure if any of these are needed for correct lighting. float CubeNormals[6][3] = { {ONORM, 0, 0}, {-ONORM, 0, 0}, {0, ONORM, 0}, {0, -ONORM, 0}, {0, 0, ONORM}, {0, 0, -ONORM} }; */ float CubeNormals[3][3] = { {0, -ONORM, 0}, {0, 0, ONORM}, {ONORM, 0, 0} }; float CubeVertices[8][3] = { {-1.0,-1.0,-1.0}, {1.0,-1.0,-1.0}, {1.0,1.0,-1.0}, {-1.0,1.0,-1.0}, {-1.0,-1.0,1.0}, {1.0,-1.0,1.0}, {1.0,1.0,1.0}, {-1.0,1.0,1.0} }; float origin[3] = { 0.0, 0.0, 0.0 }; #define UP_NORM Octo[2] #define DOWN_NORM Octo[5] #define ORIGIN origin /* vertices & normals for octagon in xy plane */ float ogverts[8][3]; /* vertices for octagon in xy plane, z=1 */ float ogvertsplus[8][3]; float Pi; static void init_stuff(void) { float cos45; int i; static int first = 1; if (first) { first = 0; cos45 = cos(atan(1.0)); for (i = 0; i < 8; i++) { ogverts[i][Z] = 0.0; ogvertsplus[i][Z] = 1.0; } ogverts[0][X] = ogvertsplus[0][X] = 1.0; ogverts[0][Y] = ogvertsplus[0][Y] = 0.0; ogverts[1][X] = ogvertsplus[1][X] = cos45; ogverts[1][Y] = ogvertsplus[1][Y] = cos45; ogverts[2][X] = ogvertsplus[2][X] = 0.0; ogverts[2][Y] = ogvertsplus[2][Y] = 1.0; ogverts[3][X] = ogvertsplus[3][X] = -cos45; ogverts[3][Y] = ogvertsplus[3][Y] = cos45; ogverts[4][X] = ogvertsplus[4][X] = -1.0; ogverts[4][Y] = ogvertsplus[4][Y] = 0.0; ogverts[5][X] = ogvertsplus[5][X] = -cos45; ogverts[5][Y] = ogvertsplus[5][Y] = -cos45; ogverts[6][X] = ogvertsplus[6][X] = 0.0; ogverts[6][Y] = ogvertsplus[6][Y] = -1.0; ogverts[7][X] = ogvertsplus[7][X] = cos45; ogverts[7][Y] = ogvertsplus[7][Y] = -cos45; Pi = 4.0 * atan(1.0); } return; } void gsd_plus(float *center, int colr, float siz) { float v1[3], v2[3]; gsd_color_func(colr); siz *= .5; v1[Z] = v2[Z] = center[Z]; v1[X] = v2[X] = center[X]; v1[Y] = center[Y] - siz; v2[Y] = center[Y] + siz; gsd_bgnline(); gsd_vert_func(v1); gsd_vert_func(v2); gsd_endline(); v1[Y] = v2[Y] = center[Y]; v1[X] = center[X] - siz; v2[X] = center[X] + siz; gsd_bgnline(); gsd_vert_func(v1); gsd_vert_func(v2); gsd_endline(); return; } /* TODO: remove fudge, instead fudge the Z buffer */ void gsd_line_onsurf(geosurf * gs, float *v1, float *v2) { int i, np; Point3 *pts; float fudge; pts = gsdrape_get_segments(gs, v1, v2, &np); if (pts) { fudge = FUDGE(gs); gsd_bgnline(); for (i = 0; i < np; i++) { /* ACS */ /* pts[i][Z] += fudge;*/ pts[i][Z] *= fudge; gsd_vert_func(pts[i]); } gsd_endline(); /* fix Z values? */ v1[Z] = pts[0][Z]; v2[Z] = pts[np - 1][Z]; } return; } /* TODO: remove fudge, instead fudge the Z buffer */ /* Like above, except only draws first n points of line, or np, * whichever is less. Returns number of points used. Fills * pt with last pt drawn. */ int gsd_nline_onsurf(geosurf * gs, float *v1, float *v2, float *pt, int n) { int i, np, pdraw; Point3 *pts; float fudge; pts = gsdrape_get_segments(gs, v1, v2, &np); if (pts) { pdraw = n < np ? n : np; fudge = FUDGE(gs); gsd_bgnline(); for (i = 0; i < pdraw; i++) { pts[i][Z] += fudge; gsd_vert_func(pts[i]); } gsd_endline(); pt[X] = pts[i - 1][X]; pt[Y] = pts[i - 1][Y]; /* fix Z values? */ v1[Z] = pts[0][Z]; v2[Z] = pts[np - 1][Z]; return (i); } return (0); } /* Note gs: NULL if flat */ void gsd_x(geosurf * gs, float *center, int colr, float siz) { float v1[3], v2[3]; gsd_color_func(colr); siz *= .5; v1[Z] = v2[Z] = center[Z]; v1[X] = center[X] - siz; v2[X] = center[X] + siz; v1[Y] = center[Y] - siz; v2[Y] = center[Y] + siz; if (gs) { gsd_line_onsurf(gs, v1, v2); } else { gsd_bgnline(); gsd_vert_func(v1); gsd_vert_func(v2); gsd_endline(); } v1[X] = center[X] - siz; v2[X] = center[X] + siz; v1[Y] = center[Y] + siz; v2[Y] = center[Y] - siz; if (gs) { gsd_line_onsurf(gs, v1, v2); } else { gsd_bgnline(); gsd_vert_func(v1); gsd_vert_func(v2); gsd_endline(); } return; } void gsd_diamond(float *center, unsigned long colr, float siz) { int preshade; /* seems right, but isn't siz *= .5; */ gsd_pushmatrix(); gsd_translate(center[X], center[Y], center[Z]); gsd_scale(siz, siz, siz); preshade = gsd_getshademodel(); gsd_shademodel(0); /* want flat shading */ gsd_bgnpolygon(); gsd_litvert_func(OctoN[0], colr, Octo[0]); gsd_litvert_func(OctoN[0], colr, Octo[1]); gsd_litvert_func(OctoN[0], colr, Octo[2]); gsd_endpolygon(); gsd_bgnpolygon(); gsd_litvert_func(OctoN[1], colr, Octo[2]); gsd_litvert_func(OctoN[1], colr, Octo[1]); gsd_litvert_func(OctoN[1], colr, Octo[3]); gsd_endpolygon(); gsd_bgnpolygon(); gsd_litvert_func(OctoN[2], colr, Octo[2]); gsd_litvert_func(OctoN[2], colr, Octo[4]); gsd_litvert_func(OctoN[2], colr, Octo[0]); gsd_endpolygon(); gsd_bgnpolygon(); gsd_litvert_func(OctoN[3], colr, Octo[2]); gsd_litvert_func(OctoN[3], colr, Octo[3]); gsd_litvert_func(OctoN[3], colr, Octo[4]); gsd_endpolygon(); gsd_bgnpolygon(); gsd_litvert_func(OctoN[4], colr, Octo[0]); gsd_litvert_func(OctoN[4], colr, Octo[5]); gsd_litvert_func(OctoN[4], colr, Octo[1]); gsd_endpolygon(); gsd_bgnpolygon(); gsd_litvert_func(OctoN[5], colr, Octo[1]); gsd_litvert_func(OctoN[5], colr, Octo[5]); gsd_litvert_func(OctoN[5], colr, Octo[3]); gsd_endpolygon(); gsd_bgnpolygon(); gsd_litvert_func(OctoN[6], colr, Octo[5]); gsd_litvert_func(OctoN[6], colr, Octo[0]); gsd_litvert_func(OctoN[6], colr, Octo[4]); gsd_endpolygon(); gsd_bgnpolygon(); gsd_litvert_func(OctoN[7], colr, Octo[5]); gsd_litvert_func(OctoN[7], colr, Octo[4]); gsd_litvert_func(OctoN[7], colr, Octo[3]); gsd_endpolygon(); #ifdef OCT_SHADED { gsd_bgntmesh(); gsd_litvert_func(Octo[0], colr, Octo[0]); gsd_litvert_func(Octo[1], colr, Octo[1]); gsd_swaptmesh(); gsd_litvert_func(Octo[2], colr, Octo[2]); gsd_swaptmesh(); gsd_litvert_func(Octo[4], colr, Octo[4]); gsd_swaptmesh(); gsd_litvert_func(Octo[5], colr, Octo[5]); gsd_swaptmesh(); gsd_litvert_func(Octo[1], colr, Octo[1]); gsd_litvert_func(Octo[3], colr, Octo[3]); gsd_litvert_func(Octo[2], colr, Octo[2]); gsd_swaptmesh(); gsd_litvert_func(Octo[4], colr, Octo[4]); gsd_swaptmesh(); gsd_litvert_func(Octo[5], colr, Octo[5]); gsd_swaptmesh(); gsd_litvert_func(Octo[1], colr, Octo[1]); gsd_endtmesh(); } #endif gsd_popmatrix(); gsd_shademodel(preshade); return; } void gsd_cube(float *center, unsigned long colr, float siz) { /* added by Hamish Bowman Nov 2005 */ int preshade; /* see gsd_diamond() "seems right, but isn't" */ siz *= .5; gsd_pushmatrix(); gsd_translate(center[X], center[Y], center[Z]); gsd_scale(siz, siz, siz); preshade = gsd_getshademodel(); gsd_shademodel(0); /* want flat shading */ /* N wall: */ gsd_bgnpolygon(); gsd_litvert_func(CubeNormals[0], colr, CubeVertices[2]); gsd_litvert_func(CubeNormals[0], colr, CubeVertices[3]); gsd_litvert_func(CubeNormals[0], colr, CubeVertices[7]); gsd_litvert_func(CubeNormals[0], colr, CubeVertices[6]); gsd_endpolygon(); /* S wall: */ gsd_bgnpolygon(); gsd_litvert_func(CubeNormals[0], colr, CubeVertices[1]); gsd_litvert_func(CubeNormals[0], colr, CubeVertices[5]); gsd_litvert_func(CubeNormals[0], colr, CubeVertices[4]); gsd_litvert_func(CubeNormals[0], colr, CubeVertices[0]); gsd_endpolygon(); /* E wall: */ gsd_bgnpolygon(); gsd_litvert_func(CubeNormals[1], colr, CubeVertices[2]); gsd_litvert_func(CubeNormals[1], colr, CubeVertices[6]); gsd_litvert_func(CubeNormals[1], colr, CubeVertices[5]); gsd_litvert_func(CubeNormals[1], colr, CubeVertices[1]); gsd_endpolygon(); /* W wall: */ gsd_bgnpolygon(); gsd_litvert_func(CubeNormals[1], colr, CubeVertices[0]); gsd_litvert_func(CubeNormals[1], colr, CubeVertices[4]); gsd_litvert_func(CubeNormals[1], colr, CubeVertices[7]); gsd_litvert_func(CubeNormals[1], colr, CubeVertices[3]); gsd_endpolygon(); /* lower wall: */ gsd_bgnpolygon(); gsd_litvert_func(CubeNormals[2], colr, CubeVertices[0]); gsd_litvert_func(CubeNormals[2], colr, CubeVertices[1]); gsd_litvert_func(CubeNormals[2], colr, CubeVertices[2]); gsd_litvert_func(CubeNormals[2], colr, CubeVertices[3]); gsd_endpolygon(); /* top wall: */ gsd_bgnpolygon(); gsd_litvert_func(CubeNormals[2], colr, CubeVertices[4]); gsd_litvert_func(CubeNormals[2], colr, CubeVertices[5]); gsd_litvert_func(CubeNormals[2], colr, CubeVertices[6]); gsd_litvert_func(CubeNormals[2], colr, CubeVertices[7]); gsd_endpolygon(); gsd_popmatrix(); gsd_shademodel(preshade); return; } void gsd_draw_box(float *center, unsigned long colr, float siz) { /* added by Hamish Bowman Nov 2005 */ /* see gsd_diamond() "seems right, but isn't" */ siz *= .5; gsd_pushmatrix(); gsd_translate(center[X], center[Y], center[Z]); gsd_scale(siz, siz, siz); gsd_color_func(colr); gsd_bgnline(); /* N wall */ gsd_vert_func(CubeVertices[2]); gsd_vert_func(CubeVertices[3]); gsd_vert_func(CubeVertices[7]); gsd_vert_func(CubeVertices[6]); gsd_vert_func(CubeVertices[2]); gsd_endline(); gsd_bgnline(); /* S wall */ gsd_vert_func(CubeVertices[1]); gsd_vert_func(CubeVertices[5]); gsd_vert_func(CubeVertices[4]); gsd_vert_func(CubeVertices[0]); gsd_vert_func(CubeVertices[1]); gsd_endline(); gsd_bgnline(); gsd_vert_func(CubeVertices[1]); gsd_vert_func(CubeVertices[2]); gsd_endline(); gsd_bgnline(); gsd_vert_func(CubeVertices[3]); gsd_vert_func(CubeVertices[0]); gsd_endline(); gsd_bgnline(); gsd_vert_func(CubeVertices[5]); gsd_vert_func(CubeVertices[6]); gsd_endline(); gsd_bgnline(); gsd_vert_func(CubeVertices[4]); gsd_vert_func(CubeVertices[7]); gsd_endline(); gsd_popmatrix(); return; } void gsd_drawsphere(float *center, unsigned long colr, float siz) { siz *= .5; /* siz is diameter, gsd_sphere uses radius */ gsd_color_func(colr); gsd_sphere(center, siz); return; } void gsd_diamond_lines(void) { gsd_bgnline(); gsd_vert_func(Octo[0]); gsd_vert_func(Octo[3]); gsd_endline(); gsd_bgnline(); gsd_vert_func(Octo[1]); gsd_vert_func(Octo[4]); gsd_endline(); gsd_bgnline(); gsd_vert_func(Octo[2]); gsd_vert_func(Octo[5]); gsd_endline(); return; } void gsd_draw_asterisk(float *center, unsigned long colr, float siz) { float angle; angle = 45.; /* degrees */ gsd_pushmatrix(); gsd_translate(center[X], center[Y], center[Z]); gsd_scale(siz, siz, siz); gsd_color_func(colr); gsd_diamond_lines(); gsd_pushmatrix(); gsd_rot(angle, 'x'); gsd_diamond_lines(); gsd_popmatrix(); gsd_pushmatrix(); gsd_rot(-angle, 'x'); gsd_diamond_lines(); gsd_popmatrix(); gsd_pushmatrix(); gsd_rot(angle, 'y'); gsd_diamond_lines(); gsd_popmatrix(); gsd_pushmatrix(); gsd_rot(-angle, 'y'); gsd_diamond_lines(); gsd_popmatrix(); gsd_pushmatrix(); gsd_rot(angle, 'z'); gsd_diamond_lines(); gsd_popmatrix(); gsd_pushmatrix(); gsd_rot(-angle, 'z'); gsd_diamond_lines(); gsd_popmatrix(); gsd_popmatrix(); return; } void gsd_draw_gyro(float *center, unsigned long colr, float siz) { int i; gsd_pushmatrix(); gsd_translate(center[X], center[Y], center[Z]); gsd_scale(siz, siz, siz); gsd_color_func(colr); /* vert axis */ gsd_bgnline(); gsd_vert_func(Octo[2]); gsd_vert_func(Octo[5]); gsd_endline(); /* spokes */ gsd_pushmatrix(); for (i = 0; i < 6; i++) { gsd_rot(30., 'z'); gsd_bgnline(); gsd_vert_func(Octo[0]); gsd_vert_func(Octo[3]); gsd_endline(); } gsd_popmatrix(); gsd_color_func(colr); gsd_circ(0., 0., 1.); gsd_pushmatrix(); gsd_rot(90., 'x'); gsd_circ(0., 0., 1.); gsd_popmatrix(); gsd_pushmatrix(); gsd_rot(90., 'y'); gsd_circ(0., 0., 1.); gsd_popmatrix(); gsd_popmatrix(); return; } void gsd_3dcursor(float *pt) { float big, vert[3]; big = 10000.; gsd_bgnline(); vert[X] = pt[X]; vert[Y] = pt[Y]; vert[Z] = big; gsd_vert_func(vert); vert[Z] = -big; gsd_vert_func(vert); gsd_endline(); gsd_bgnline(); vert[X] = pt[X]; vert[Z] = pt[Z]; vert[Y] = big; gsd_vert_func(vert); vert[Y] = -big; gsd_vert_func(vert); gsd_endline(); gsd_bgnline(); vert[Y] = pt[Y]; vert[Z] = pt[Z]; vert[X] = big; gsd_vert_func(vert); vert[X] = -big; gsd_vert_func(vert); gsd_endline(); return; } void dir_to_slope_aspect(float *dir, float *slope, float *aspect, int degrees) { float dx, dy, dz; float costheta, theta, adjacent; dx = dir[X]; dy = dir[Y]; dz = dir[Z]; /* project vector onto plane of constant z containing * final value should be 0.0 to 3600.0 */ if (dx == 0 && dy == 0) { *aspect = 0.; } else { if (dx == 0) { theta = 90.0; } else { costheta = dx / sqrt(dx * dx + dy * dy); theta = acos(costheta); } if (dy < 0) { theta = (2 * Pi) - theta; } *aspect = theta; } /* project vector onto plane of constant y containing * final value should be -900.0 (looking up) to 900.0 (looking down) */ if (dz == 0) { theta = 0.0; } else if (dx == 0 && dy == 0) { theta = Pi / 2.; } else { adjacent = sqrt(dx * dx + dy * dy); costheta = adjacent / sqrt(adjacent * adjacent + dz * dz); theta = acos(costheta); } if (dz > 0) { theta = -theta; } *slope = theta; if (degrees) { *aspect = *aspect * (180. / Pi); *slope = *slope * (180. / Pi); } return; } /************************************************************** * Function to draw North Arrow takes OpenGL coords and size *************************************************************/ int gsd_north_arrow (float *pos2, float len, GLuint fontbase) { char *txt; float v[4][3]; float base[2][3]; float Ntop[] = { 0.0, 0.0, 1.0 }; base[0][Z] = base[1][Z] = v[0][Z] = v[1][Z] = v[2][Z] = v[3][Z] = pos2[Z]; base[0][X] = pos2[X] - len / 16.; base[1][X] = pos2[X] + len / 16.; base[0][Y] = base[1][Y] = pos2[Y] - len / 2.; v[0][X] = v[2][X] = pos2[X]; v[1][X] = pos2[X] + len / 8.; v[3][X] = pos2[X] - len / 8.; v[0][Y] = pos2[Y] + .2 * len; v[1][Y] = v[3][Y] = pos2[Y] + .1 * len; v[2][Y] = pos2[Y] + .5 * len; /* make sure we are drawing in front buffer */ GS_set_draw(GSD_FRONT); gsd_pushmatrix(); gsd_do_scale(1); glNormal3fv(Ntop); gsd_color_func(0x000000); gsd_bgnpolygon(); glVertex3fv(base[0]); glVertex3fv(base[1]); glVertex3fv(v[0]); gsd_endpolygon(); gsd_bgnpolygon(); glVertex3fv(v[0]); glVertex3fv(v[1]); glVertex3fv(v[2]); glVertex3fv(v[0]); gsd_endpolygon(); gsd_bgnpolygon(); glVertex3fv(v[0]); glVertex3fv(v[2]); glVertex3fv(v[3]); glVertex3fv(v[0]); gsd_endpolygon(); /* draw N for North */ /* Need to pick a nice generic font */ /* TODO -- project text position off arrow * bottom along azimuth */ gsd_color_func(0x000000); txt = "North"; /* adjust position of N text */ base[0][X] -= gsd_get_txtwidth(txt, 18) - 20.; base[0][Y] -= gsd_get_txtheight(18) - 20. ; glRasterPos3fv(base[0]); glListBase(fontbase); glCallLists(strlen(txt), GL_BYTE, (GLubyte *) txt); GS_done_draw(); gsd_popmatrix(); gsd_flush(); return (1); } /**************************************************************/ /* siz is height, sz is global exag to correct for. * If onsurf in non-null, z component of dir is dropped and * line-on-suf is used, resulting in length of arrow being proportional * to slope */ int gsd_arrow(float *center, unsigned long colr, float siz, float *dir, float sz, geosurf * onsurf) { float slope, aspect; float tmp[3]; static int first = 1; if (first) { init_stuff(); first = 0; } dir[Z] /= sz; GS_v3norm(dir); if (NULL != onsurf) { float base[3], tip[3], len; base[X] = center[X]; base[Y] = center[Y]; /* project dir to surface, after zexag */ len = GS_P2distance(ORIGIN, dir); /* in case dir isn't normalized */ tip[X] = center[X] + dir[X] * len * siz; tip[Y] = center[Y] + dir[Y] * len * siz; return gsd_arrow_onsurf(base, tip, colr, 2, onsurf); } dir_to_slope_aspect(dir, &slope, &aspect, 1); gsd_pushmatrix(); gsd_translate(center[X], center[Y], center[Z]); gsd_scale(1.0, 1.0, 1.0 / sz); gsd_rot(aspect + 90, 'z'); gsd_rot(slope + 90., 'x'); gsd_scale(siz, siz, siz); gsd_color_func(colr); tmp[X] = 0.2; tmp[Y] = 0.0; tmp[Z] = 0.65; gsd_bgnline(); gsd_vert_func(ORIGIN); gsd_vert_func(UP_NORM); gsd_endline(); gsd_bgnline(); gsd_vert_func(tmp); gsd_vert_func(UP_NORM); tmp[X] = -0.2; gsd_vert_func(tmp); gsd_endline(); gsd_popmatrix(); return (1); } /**************************************************************/ int gsd_arrow_onsurf(float *base, float *tip, unsigned long colr, int wid, geosurf * gs) { static int first = 1; if (first) { init_stuff(); first = 0; } gsd_linewidth(wid); gsd_color_func(colr); /* DEBUG fprintf(stderr,"%f %f -> ", base[X], base[Y]); fprintf(stderr,"%f %f\n", tip[X], tip[Y]); */ gsd_line_onsurf(gs, base, tip); #ifdef DO_SPHERE_BASE { GS_v3dir(tip, base, dir0); GS_v3mag(dir0, &len); gsd_disc(base[X], base[Y], len / 10.); } #endif #ifdef ARROW_READY { base[Z] = tip[Z] = 0.0; GS_v3dir(tip, base, dir0); /* DEBUG fprintf(stderr,"dir0: %f %f %f\n", dir0[X], dir0[Y], dir0[Z]); */ /* rotate this direction 90 degrees */ GS_v3cross(dir0, UP_NORM, dir2); GS_v3mag(dir0, &len); GS_v3eq(dir1, dir0); /* DEBUG fprintf(stderr,"len: %f\n", len); fprintf(stderr,"a-dir1: %f %f %f\n", dir1[X], dir1[Y], dir1[Z]); fprintf(stderr,"a-dir2: %f %f %f\n", dir2[X], dir2[Y], dir2[Z]); */ dim1 = len * .7; dim2 = len * .2; GS_v3mult(dir1, dim1); GS_v3mult(dir2, dim2); /* DEBUG fprintf(stderr,"b-dir1: %f %f %f\n", dir1[X], dir1[Y], dir1[Z]); fprintf(stderr,"b-dir2: %f %f %f\n", dir2[X], dir2[Y], dir2[Z]); */ GS_v3eq(tmp, base); GS_v3add(tmp, dir1); GS_v3add(tmp, dir2); /* DEBUG fprintf(stderr,"%f %f -> ", tmp[X], tmp[Y]); */ gsd_line_onsurf(gs, tmp, tip); GS_v3cross(dir0, DOWN_NORM, dir2); GS_v3mult(dir2, dim2); GS_v3eq(tmp, base); /* DEBUG fprintf(stderr,"dir1: %f %f %f\n", dir1[X], dir1[Y], dir1[Z]); fprintf(stderr,"dir2: %f %f %f\n", dir2[X], dir2[Y], dir2[Z]); */ GS_v3add(tmp, dir1); GS_v3add(tmp, dir2); /* DEBUG fprintf(stderr,"%f %f\n", tmp[X], tmp[Y]); */ gsd_line_onsurf(gs, tip, tmp); } #endif return (0); } /**************************************************************/ /* siz1 is height, siz2 is diameter */ void gsd_3darrow(float *center, unsigned long colr, float siz1, float siz2, float *dir, float sz) { float slope, aspect; int preshade; static int first = 1; static int list; dir[Z] /= sz; GS_v3norm(dir); dir_to_slope_aspect(dir, &slope, &aspect, 1); #ifdef DEBUG { static int debugint = 1; if (debugint > 100) { fprintf(stderr, "pt: %f,%f,%f dir: %f,%f,%f slope: %f aspect: %f\n", center[X], center[Y], center[Z], dir[X], dir[Y], dir[Z], slope, aspect); debugint = 1; } debugint++; } #endif preshade = gsd_getshademodel(); /* gsd_shademodel(0); want flat shading? */ gsd_pushmatrix(); gsd_translate(center[X], center[Y], center[Z]); gsd_scale(1.0, 1.0, 1.0 / sz); gsd_rot(aspect + 90, 'z'); gsd_rot(slope + 90., 'x'); gsd_scale(siz2, siz2, siz1); gsd_color_func(colr); if (first) { /* combine these into an object */ first = 0; list = gsd_makelist(); gsd_bgnlist(list, 1); gsd_backface(1); gsd_pushmatrix(); gsd_scale(.10, .10, .75); /* narrow cyl */ primitive_cylinder(colr, 0); gsd_popmatrix(); gsd_pushmatrix(); gsd_translate(0.0, 0.0, .60); gsd_scale(0.3, 0.3, 0.4); /* cone */ primitive_cone(colr); gsd_popmatrix(); gsd_backface(0); gsd_endlist(); } else { gsd_calllist(list); } gsd_popmatrix(); gsd_shademodel(preshade); return; } /* primitives only called after transforms */ /* center is actually center at base of 8 sided cone */ void primitive_cone(unsigned long col) { float tip[3]; static int first = 1; if (first) { init_stuff(); first = 0; } tip[X] = tip[Y] = 0.0; tip[Z] = 1.0; gsd_bgntfan(); gsd_litvert_func2(UP_NORM, col, tip); gsd_litvert_func2(ogverts[0], col, ogverts[0]); gsd_litvert_func2(ogverts[1], col, ogverts[1]); gsd_litvert_func2(ogverts[2], col, ogverts[2]); gsd_litvert_func2(ogverts[3], col, ogverts[3]); gsd_litvert_func2(ogverts[4], col, ogverts[4]); gsd_litvert_func2(ogverts[5], col, ogverts[5]); gsd_litvert_func2(ogverts[6], col, ogverts[6]); gsd_litvert_func2(ogverts[7], col, ogverts[7]); gsd_litvert_func2(ogverts[0], col, ogverts[0]); gsd_endtfan(); return; } /* primitives only called after transforms */ /* center is actually center at base of 8 sided cylinder */ void primitive_cylinder(unsigned long col, int caps) { static int first = 1; if (first) { init_stuff(); first = 0; } gsd_bgnqstrip(); gsd_litvert_func2(ogverts[0], col, ogvertsplus[0]); gsd_litvert_func2(ogverts[0], col, ogverts[0]); gsd_litvert_func2(ogverts[1], col, ogvertsplus[1]); gsd_litvert_func2(ogverts[1], col, ogverts[1]); gsd_litvert_func2(ogverts[2], col, ogvertsplus[2]); gsd_litvert_func2(ogverts[2], col, ogverts[2]); gsd_litvert_func2(ogverts[3], col, ogvertsplus[3]); gsd_litvert_func2(ogverts[3], col, ogverts[3]); gsd_litvert_func2(ogverts[4], col, ogvertsplus[4]); gsd_litvert_func2(ogverts[4], col, ogverts[4]); gsd_litvert_func2(ogverts[5], col, ogvertsplus[5]); gsd_litvert_func2(ogverts[5], col, ogverts[5]); gsd_litvert_func2(ogverts[6], col, ogvertsplus[6]); gsd_litvert_func2(ogverts[6], col, ogverts[6]); gsd_litvert_func2(ogverts[7], col, ogvertsplus[7]); gsd_litvert_func2(ogverts[7], col, ogverts[7]); gsd_litvert_func2(ogverts[0], col, ogvertsplus[0]); gsd_litvert_func2(ogverts[0], col, ogverts[0]); gsd_endqstrip(); if (caps) { /* draw top */ gsd_bgntfan(); gsd_litvert_func2(UP_NORM, col, UP_NORM); gsd_litvert_func2(UP_NORM, col, ogvertsplus[0]); gsd_litvert_func2(UP_NORM, col, ogvertsplus[1]); gsd_litvert_func2(UP_NORM, col, ogvertsplus[2]); gsd_litvert_func2(UP_NORM, col, ogvertsplus[3]); gsd_litvert_func2(UP_NORM, col, ogvertsplus[4]); gsd_litvert_func2(UP_NORM, col, ogvertsplus[5]); gsd_litvert_func2(UP_NORM, col, ogvertsplus[6]); gsd_litvert_func2(UP_NORM, col, ogvertsplus[7]); gsd_litvert_func2(UP_NORM, col, ogvertsplus[0]); gsd_endtfan(); /* draw bottom */ gsd_bgntfan(); gsd_litvert_func2(DOWN_NORM, col, ORIGIN); gsd_litvert_func2(DOWN_NORM, col, ogverts[0]); gsd_litvert_func2(DOWN_NORM, col, ogverts[1]); gsd_litvert_func2(DOWN_NORM, col, ogverts[2]); gsd_litvert_func2(DOWN_NORM, col, ogverts[3]); gsd_litvert_func2(DOWN_NORM, col, ogverts[4]); gsd_litvert_func2(DOWN_NORM, col, ogverts[5]); gsd_litvert_func2(DOWN_NORM, col, ogverts[6]); gsd_litvert_func2(DOWN_NORM, col, ogverts[7]); gsd_litvert_func2(DOWN_NORM, col, ogverts[0]); gsd_endtfan(); } return; } /*** ACS_MODIFY_BEGIN - sites_attribute management ********************************/ /* Draws boxes that are used for histograms by gpd_obj function in gpd.c for site_attribute management */ /* vertices for box */ float Box[8][3] = {{ 1.0, 1.0, -1.0},{-1.0, 1.0, -1.0},{-1.0, 1.0, 1.0},{ 1.0, 1.0, 1.0}, { 1.0, -1.0, -1.0},{-1.0, -1.0, -1.0},{-1.0, -1.0, 1.0},{ 1.0, -1.0, 1.0}}; float BoxN[6][3] = {{0, 0, -ONORM},{0, 0, ONORM},{0, ONORM, 0},{0, -ONORM, 0},{ONORM, 0, 0},{-ONORM, 0, 0}}; /* Warning siz is an array (we need it for scale only Z in histograms) */ void gsd_box(float *center, int colr, float *siz) { int preshade; gsd_pushmatrix(); gsd_translate(center[X], center[Y], center[Z] + siz[2]); gsd_scale(siz[0], siz[1], siz[2]); preshade = gsd_getshademodel(); gsd_shademodel(0); /* want flat shading */ /* Top */ gsd_bgnpolygon(); gsd_litvert_func(BoxN[2], colr, Box[0]); gsd_litvert_func(BoxN[2], colr, Box[1]); gsd_litvert_func(BoxN[2], colr, Box[2]); gsd_litvert_func(BoxN[2], colr, Box[3]); gsd_endpolygon(); /* Bottom */ gsd_bgnpolygon(); gsd_litvert_func(BoxN[3], colr, Box[7]); gsd_litvert_func(BoxN[3], colr, Box[6]); gsd_litvert_func(BoxN[3], colr, Box[5]); gsd_litvert_func(BoxN[3], colr, Box[4]); gsd_endpolygon(); /* Right */ gsd_bgnpolygon(); gsd_litvert_func(BoxN[4], colr, Box[0]); gsd_litvert_func(BoxN[4], colr, Box[3]); gsd_litvert_func(BoxN[4], colr, Box[7]); gsd_litvert_func(BoxN[4], colr, Box[4]); gsd_endpolygon(); /* Left */ gsd_bgnpolygon(); gsd_litvert_func(BoxN[5], colr, Box[1]); gsd_litvert_func(BoxN[5], colr, Box[5]); gsd_litvert_func(BoxN[5], colr, Box[6]); gsd_litvert_func(BoxN[5], colr, Box[2]); gsd_endpolygon(); /* Front */ gsd_bgnpolygon(); gsd_litvert_func(BoxN[0], colr, Box[0]); gsd_litvert_func(BoxN[0], colr, Box[4]); gsd_litvert_func(BoxN[0], colr, Box[5]); gsd_litvert_func(BoxN[0], colr, Box[1]); gsd_endpolygon(); /* Back */ gsd_bgnpolygon(); gsd_litvert_func(BoxN[1], colr, Box[3]); gsd_litvert_func(BoxN[1], colr, Box[2]); gsd_litvert_func(BoxN[1], colr, Box[6]); gsd_litvert_func(BoxN[1], colr, Box[7]); gsd_endpolygon(); gsd_popmatrix(); gsd_shademodel(preshade); return; } /*** ACS_MODIFY_END - sites_attribute management ********************************/