void gleSuperExtrusion (int ncp, /* number of contour points */ gleDouble contour[][2], /* 2D contour */ gleDouble cont_normal[][2], /* 2D contour normals */ gleDouble up[3], /* up vector for contour */ int npoints, /* numpoints in poly-line */ gleDouble point_array[][3], /* polyline */ gleColor color_array[], /* color of polyline */ gleDouble xform_array[][2][3]) /* 2D contour xforms */ { INIT_GC(); _gle_gc -> ncp = ncp; _gle_gc -> contour = contour; _gle_gc -> cont_normal = cont_normal; _gle_gc -> up = up; _gle_gc -> npoints = npoints; _gle_gc -> point_array = point_array; _gle_gc -> color_array = color_array; _gle_gc -> xform_array = xform_array; switch (__TUBE_STYLE) { case TUBE_JN_RAW: (void) extrusion_raw_join (ncp, contour, cont_normal, up, npoints, point_array, color_array, xform_array); break; case TUBE_JN_ANGLE: (void) extrusion_angle_join (ncp, contour, cont_normal, up, npoints, point_array, color_array, xform_array); break; case TUBE_JN_CUT: case TUBE_JN_ROUND: /* This routine used for both cut and round styles */ (void) extrusion_round_or_cut_join (ncp, contour, cont_normal, up, npoints, point_array, color_array, xform_array); break; default: break; } }
void gleTextureMode (int mode) { INIT_GC(); /* enable textureing by restoring the mode */ _gle_gc -> bgn_gen_texture = _gle_gc -> save_bgn_gen_texture; _gle_gc -> n3f_gen_texture = _gle_gc -> save_n3f_gen_texture; _gle_gc -> n3d_gen_texture = _gle_gc -> save_n3d_gen_texture; _gle_gc -> v3f_gen_texture = _gle_gc -> save_v3f_gen_texture; _gle_gc -> v3d_gen_texture = _gle_gc -> save_v3d_gen_texture; _gle_gc -> end_gen_texture = _gle_gc -> save_end_gen_texture; switch (mode&GLE_TEXTURE_STYLE_MASK) { case GLE_TEXTURE_VERTEX_FLAT: _gle_gc -> bgn_gen_texture = bgn_z_texgen; _gle_gc -> v3d_gen_texture = vertex_flat_texgen_v; _gle_gc -> n3d_gen_texture = 0x0; break; case GLE_TEXTURE_NORMAL_FLAT: _gle_gc -> bgn_gen_texture = bgn_z_texgen; _gle_gc -> v3d_gen_texture = normal_flat_texgen_v; _gle_gc -> n3d_gen_texture = save_normal; break; case GLE_TEXTURE_VERTEX_MODEL_FLAT: _gle_gc -> bgn_gen_texture = bgn_z_texgen; _gle_gc -> v3d_gen_texture = vertex_flat_model_v; _gle_gc -> n3d_gen_texture = 0x0; break; case GLE_TEXTURE_NORMAL_MODEL_FLAT: _gle_gc -> bgn_gen_texture = bgn_z_texgen; _gle_gc -> v3d_gen_texture = normal_flat_model_v; _gle_gc -> n3d_gen_texture = 0x0; break; case GLE_TEXTURE_VERTEX_CYL: _gle_gc -> bgn_gen_texture = bgn_z_texgen; _gle_gc -> v3d_gen_texture = vertex_cylinder_texgen_v; _gle_gc -> n3d_gen_texture = 0x0; break; case GLE_TEXTURE_NORMAL_CYL: _gle_gc -> bgn_gen_texture = bgn_z_texgen; _gle_gc -> v3d_gen_texture = normal_cylinder_texgen_v; _gle_gc -> n3d_gen_texture = save_normal; break; case GLE_TEXTURE_VERTEX_MODEL_CYL: _gle_gc -> bgn_gen_texture = bgn_z_texgen; _gle_gc -> v3d_gen_texture = vertex_cylinder_model_v; _gle_gc -> n3d_gen_texture = 0x0; break; case GLE_TEXTURE_NORMAL_MODEL_CYL: _gle_gc -> bgn_gen_texture = bgn_z_texgen; _gle_gc -> v3d_gen_texture = normal_cylinder_model_v; _gle_gc -> n3d_gen_texture = 0x0; break; case GLE_TEXTURE_VERTEX_SPH: _gle_gc -> bgn_gen_texture = bgn_sphere_texgen; _gle_gc -> v3d_gen_texture = vertex_sphere_texgen_v; _gle_gc -> n3d_gen_texture = 0x0; break; case GLE_TEXTURE_NORMAL_SPH: _gle_gc -> bgn_gen_texture = bgn_sphere_texgen; _gle_gc -> v3d_gen_texture = normal_sphere_texgen_v; _gle_gc -> n3d_gen_texture = save_normal; break; case GLE_TEXTURE_VERTEX_MODEL_SPH: _gle_gc -> bgn_gen_texture = bgn_sphere_texgen; _gle_gc -> v3d_gen_texture = vertex_sphere_model_v; _gle_gc -> n3d_gen_texture = 0x0; break; case GLE_TEXTURE_NORMAL_MODEL_SPH: _gle_gc -> bgn_gen_texture = bgn_sphere_texgen; _gle_gc -> v3d_gen_texture = normal_sphere_model_v; _gle_gc -> n3d_gen_texture = 0x0; break; default: break; } /* disable texturing, and save the mode */ if (!(mode & GLE_TEXTURE_ENABLE)) { _gle_gc -> save_bgn_gen_texture = _gle_gc -> bgn_gen_texture; _gle_gc -> save_n3f_gen_texture = _gle_gc -> n3f_gen_texture; _gle_gc -> save_n3d_gen_texture = _gle_gc -> n3d_gen_texture; _gle_gc -> save_v3f_gen_texture = _gle_gc -> v3f_gen_texture; _gle_gc -> save_v3d_gen_texture = _gle_gc -> v3d_gen_texture; _gle_gc -> save_end_gen_texture = _gle_gc -> end_gen_texture; _gle_gc -> bgn_gen_texture = 0x0; _gle_gc -> n3f_gen_texture = 0x0; _gle_gc -> n3d_gen_texture = 0x0; _gle_gc -> v3f_gen_texture = 0x0; _gle_gc -> v3d_gen_texture = 0x0; _gle_gc -> end_gen_texture = 0x0; } }
void gleSetNumSides(int nslices) { INIT_GC(); setup_circle (_gle_gc, nslices); }
int gleGetNumSides(void) { INIT_GC(); return (_gle_gc->slices); }
int gleGetJoinStyle (void) { INIT_GC(); return (extrusion_join_style); }
void gleSetJoinStyle (int style) { INIT_GC(); extrusion_join_style = style; }
void gleSpiral (int ncp, /* number of contour points */ gleDouble contour[][2], /* 2D contour */ gleDouble cont_normal[][2], /* 2D contour normals */ gleDouble up[3], /* up vector for contour */ gleDouble startRadius, gleDouble drdTheta, /* change in radius per revolution */ gleDouble startZ, gleDouble dzdTheta, /* change in Z per revolution */ gleDouble startXform[2][3], gleDouble dXformdTheta[2][3], /* tangent change xform per revolution */ gleDouble startTheta, /* start angle, in degrees */ gleDouble sweepTheta) /* sweep angle, in degrees */ { int npoints; gleDouble deltaAngle; char * mem_anchor; gleDouble *pts; gleAffine *xforms; double delta; int saved_style; double ccurr, scurr; double cprev, sprev; double cdelta, sdelta; double mA[2][2], mB[2][2]; double run[2][2]; double deltaTrans[2]; double trans[2]; int i; INIT_GC(); /* allocate sufficient memory to store path */ npoints = (int) ((((double) __TESS_SLICES) /360.0) * fabs(sweepTheta)) + 4; if (startXform == NULL) { mem_anchor = malloc (3*npoints * sizeof (gleDouble)); pts = (gleDouble *) mem_anchor; xforms = NULL; } else { mem_anchor = malloc ((1+2)* 3*npoints * sizeof (gleDouble)); pts = (gleDouble *) mem_anchor; xforms = (gleAffine *) (pts + 3*npoints); } /* compute delta angle based on number of points */ deltaAngle = (M_PI / 180.0) * sweepTheta / ((gleDouble) (npoints-3)); startTheta *= M_PI / 180.0; startTheta -= deltaAngle; /* initialize factors */ cprev = cos ((double) startTheta); sprev = sin ((double) startTheta); cdelta = cos ((double) deltaAngle); sdelta = sin ((double) deltaAngle); /* renormalize differential factors */ delta = deltaAngle / (2.0 * M_PI); dzdTheta *= delta; drdTheta *= delta; /* remember, the first point is hidden, so back-step */ startZ -= dzdTheta; startRadius -= drdTheta; /* draw spiral path using recursion relations for sine, cosine */ for (i=0; i<npoints; i++) { pts [3*i] = startRadius * cprev; pts [3*i+1] = startRadius * sprev; pts [3*i+2] = (gleDouble) startZ; startZ += dzdTheta; startRadius += drdTheta; ccurr = cprev * cdelta - sprev * sdelta; scurr = cprev * sdelta + sprev * cdelta; cprev = ccurr; sprev = scurr; } /* If there is a deformation matrix specified, then a deformation * path must be generated also */ if (startXform != NULL) { if (dXformdTheta == NULL) { for (i=0; i<npoints; i++) { xforms[i][0][0] = startXform[0][0]; xforms[i][0][1] = startXform[0][1]; xforms[i][0][2] = startXform[0][2]; xforms[i][1][0] = startXform[1][0]; xforms[i][1][1] = startXform[1][1]; xforms[i][1][2] = startXform[1][2]; } } else { /* * if there is a differential matrix specified, treat it a * a tangent (algebraic, infinitessimal) matrix. We need to * project it into the group of real 2x2 matricies. (Note that * the specified matrix is affine. We treat the translation * components linearly, and only treat the 2x2 submatrix as an * algebraic tangenet). * * For exponentiaition, we use the well known approx: * exp(x) = lim (N->inf) (1+x/N) ** N * and take N=32. */ /* initialize translation and delta translation */ deltaTrans[0] = delta * dXformdTheta[0][2]; deltaTrans[1] = delta * dXformdTheta[1][2]; trans[0] = startXform[0][2]; trans[1] = startXform[1][2]; /* prepare the tangent matrix */ delta /= 32.0; mA[0][0] = 1.0 + delta * dXformdTheta[0][0]; mA[0][1] = delta * dXformdTheta[0][1]; mA[1][0] = delta * dXformdTheta[1][0]; mA[1][1] = 1.0 + delta * dXformdTheta[1][1]; /* compute exponential of matrix */ MATRIX_PRODUCT_2X2 (mB, mA, mA); /* squared */ MATRIX_PRODUCT_2X2 (mA, mB, mB); /* 4th power */ MATRIX_PRODUCT_2X2 (mB, mA, mA); /* 8th power */ MATRIX_PRODUCT_2X2 (mA, mB, mB); /* 16th power */ MATRIX_PRODUCT_2X2 (mB, mA, mA); /* 32nd power */ /* initialize running matrix */ COPY_MATRIX_2X2 (run, startXform); /* remember, the first point is hidden -- load some, any * xform for the first point */ xforms[0][0][0] = startXform[0][0]; xforms[0][0][1] = startXform[0][1]; xforms[0][0][2] = startXform[0][2]; xforms[0][1][0] = startXform[1][0]; xforms[0][1][1] = startXform[1][1]; xforms[0][1][2] = startXform[1][2]; for (i=1; i<npoints; i++) { #ifdef FUNKY_C xforms[6*i] = run[0][0]; xforms[6*i+1] = run[0][1]; xforms[6*i+3] = run[1][0]; xforms[6*i+4] = run[1][1]; #endif /* FUNKY_C */ xforms[i][0][0] = run[0][0]; xforms[i][0][1] = run[0][1]; xforms[i][1][0] = run[1][0]; xforms[i][1][1] = run[1][1]; /* integrate to get exponential matrix */ /* (Note that the group action is a left-action -- * i.e. multiply on the left (not the right)) */ MATRIX_PRODUCT_2X2 (mA, mB, run); COPY_MATRIX_2X2 (run, mA); #ifdef FUNKY_C xforms[6*i+2] = trans [0]; xforms[6*i+5] = trans [1]; #endif /* FUNKY_C */ xforms[i][0][2] = trans [0]; xforms[i][1][2] = trans [1]; trans[0] += deltaTrans[0]; trans[1] += deltaTrans[1]; } } } /* save the current join style */ saved_style = extrusion_join_style; /* Allow only angle joins (for performance reasons). * The idea is that if the tesselation is fine enough, then an angle * join should be sufficient to get the desired visual quality. A * raw join would look terrible, an cut join would leave garbage * everywhere, and a round join will over-tesselate (and thus * should be avoided for performance reasons). */ extrusion_join_style &= ~TUBE_JN_MASK; extrusion_join_style |= TUBE_JN_ANGLE; gleSuperExtrusion (ncp, contour, cont_normal, up, npoints, (gleVector *) pts, NULL, xforms); /* restore the join style */ extrusion_join_style = saved_style; free (mem_anchor); }
static void gen_polycone (int npoints, gleDouble point_array[][3], gleColor color_array[], gleDouble radius, gleDouble xform_array[][2][3]) { int saved_style; gleTwoVec *circle, *norm; int i, nslices; double v21[3]; double len; gleDouble up[3]; INIT_GC(); nslices = __TESS_SLICES; circle = __TESS_CIRCLE; norm = __TESS_NORM; /* this if statement forces this routine into double-duty for * both the polycone and the polycylinder routines */ if (xform_array != NULL) radius = 1.0; /* draw a norm using recursion relations */ for (i=0; i<nslices; i++) { circle [i][0] = radius * norm[i][0]; circle [i][1] = radius * norm[i][1]; } /* avoid degenerate vectors */ /* first, find a non-zero length segment */ i=0; FIND_NON_DEGENERATE_POINT(i,npoints,len,v21,point_array) if (i == npoints) return; /* next, check to see if this segment lies along x-axis */ if ((v21[0] == 0.0) && (v21[2] == 0.0)) { up[0] = up[1] = up[2] = 1.0; } else { up[0] = up[2] = 0.0; up[1] = 1.0; } /* save the current join style */ saved_style = extrusion_join_style; extrusion_join_style |= TUBE_CONTOUR_CLOSED; /* if lighting is not turned on, don't send normals. * MMODE is a good indicator of whether lighting is active */ if (!__IS_LIGHTING_ON) { gleSuperExtrusion (nslices, circle, NULL, up, npoints, point_array, color_array, xform_array); } else { gleSuperExtrusion (nslices, circle, norm, up, npoints, point_array, color_array, xform_array); } /* restore the join style */ extrusion_join_style = saved_style; }