#include #include #include #include #include #include #include #include #include #include "globals.h" #include "util.h" /* sets up the viewport */ void set_viewport(RenderState state) { int vp_left, vp_right, vp_bottom, vp_top; win_stat(state.winview, state.orgview, state.sizeview); vp_left = 0; vp_right = state.sizeview[X]; vp_bottom = 0; vp_top = state.sizeview[Y]; viewport(vp_left, vp_right, vp_bottom, vp_top); } /* sets up the views, either in perspective of parallel projection */ void set_view(RenderState state) { float aspect_ratio; aspect_ratio = ((float)state.sizeview[X])/((float)state.sizeview[Y]); /* perpective */ if (state.persp) { if (state.stereo_on) { perspective(state.angle, 0.5*aspect_ratio, state.near, state.far); } else { perspective(state.angle, aspect_ratio, state.near, state.far); } } /* parallel */ else { ortho(state.left*(1.0/aspect_ratio), state.right*(1.0/aspect_ratio), state.bottom, state.top, state.near, state.far); } lookat(state.cop[X]-state.dcop[X], state.cop[Y], state.cop[Z], state.vrp[X], state.vrp[Y], state.vrp[Z], 10.0*(state.twist)); } /* applies the transformations to the cumulitative matrix */ void transformations(RenderState state) { translate(state.dx, state.dy, state.dz); scale(state.scale_factor, state.scale_factor, state.scale_factor); if (state.auto_wobble) { float speed; /* factor to produce reasonable wobble speed */ speed = 10.0*elapsed_time(&state.run_time); if (gstate.wobble_amplitude >= 90.0) { /* do continuous rotation */ rot(50.0*(speed/state.wobble_period) - state.init_wobble_angle, 'y'); } else rot(state.wobble_amplitude*sin(speed/state.wobble_period) - state.init_wobble_angle, 'y'); } multmatrix(cm); } /* updates the cumulitative matrix */ void updatematrix(RenderState state) { pushmatrix(); loadmatrix(id); switch (state.axis) { case (XY_AXIS): state.txr = fmodf(state.xrot+state.txr, 360.0); state.tyr = fmodf(state.yrot+state.tyr, 360.0); rot(state.xrot, 'x'); rot(state.yrot, 'y'); break; case (Z_AXIS): state.tzr = fmodf(state.zrot+state.tzr, 360.0); rot(state.zrot,'z'); break; case (NO_AXIS): break; default: break; } multmatrix(cm); getmatrix(cm); popmatrix(); } /* returns the theta angle in polar coordinates between the two vectors v1 and v2 */ float get_theta(float *v1, float *v2) { float angle, rad; float v[3] = {v2[X]-v1[X], v2[Y]-v1[Y], v2[Z]-v1[Z]}; rad = distance(v1, v2); if (rad == 0.0) return 0.0; angle = asin(v[Y]/rad); return angle; } /* returns the phi angle in polar coordinates between the two vectors v1 and v2 given the theta angle */ float get_phi(float *v1, float *v2, float t) { float angle, rad, cost; float v[3] = {v2[X]-v1[X], v2[Y]-v1[Y], v2[Z]-v1[Z]}; rad = distance(v1, v2); if (rad == 0.0) return 0.0; cost = cos(t); if (cost) angle = acos(v[X]/(rad*cost)); else angle = 0.0; return angle; } /* adjusts the twist angle at the north and south poles by twisting an extra 180 degrees */ float adjust_twist_angle(float old_theta, float new_theta, float twist_angle) { if ((rad_to_deg(old_theta) > 350.0 && rad_to_deg(new_theta) < 10.0) || (rad_to_deg(old_theta) < -350.0 && rad_to_deg(new_theta) > -10.0)) { return twist_angle; } if ((rad_to_deg(old_theta) < 90.0 && rad_to_deg(new_theta) >= 90.0) || (rad_to_deg(old_theta) > 90.0 && rad_to_deg(new_theta) <= 90.0) || (rad_to_deg(old_theta) < 270.0 && rad_to_deg(new_theta) >= 270.0) || (rad_to_deg(old_theta) > 270.0 && rad_to_deg(new_theta) <= 270.0) || (rad_to_deg(old_theta) < -90.0 && rad_to_deg(new_theta) >= -90.0) || (rad_to_deg(old_theta) > -90.0 && rad_to_deg(new_theta) <= -90.0) || (rad_to_deg(old_theta) < -270.0 && rad_to_deg(new_theta) >= -270.0) || (rad_to_deg(old_theta) > -270.0 && rad_to_deg(new_theta) <= -270.0)) { return fmodf(twist_angle+180.0, 360.0); } return twist_angle; } /* creates a display list for obj, the function display_list must generate the display list, and return the number of polygons generated by the list */ int make_display_list(Object obj, DisplayList display_list) { int num_polys; /* if this object already exits, delete it */ if (isobj(obj)) delobj(obj); /* begin display list */ makeobj(obj); /* generate the display list */ num_polys = display_list(); /* end display list */ closeobj(); /* clean up any fragments */ compactify(obj); return num_polys; }