// copyright Min Zhong, cs838 proj2, April, 2000 #include "viewer.h" #include "vector.h" #define FOLLOW_WT 0.2 // for smooth transition bw frames, the smaller the close to prev frame // if mouse stroke to left: zoomOut; to right: zoomIn void zoom(int mouseDragXdist, double &fieldOfView) { double amt = mouseDragXdist / 100.0f; // some random positive amt fieldOfView += amt; if (fieldOfView > 180) fieldOfView = 180; if (fieldOfView < 0) fieldOfView = 0; mdebug(DEBUG_STAGE,"field of view = %2.2lf\n", fieldOfView); } void camera_omin(int frame_cnt, double *trans, double look[3], double eye[3]) { double *start_pos; double *end_pos; double dist[3]; double unit_dir[3]; // general dir the fig is following double theta_xz; // ang in xz plan double model_mat[16]; double eye_v4[] = {0, 0, 0, 1}; // to get eye pt start_pos = trans; end_pos = trans + (frame_cnt-1)*3; v3_sub(end_pos, start_pos, dist); mdebug(DEBUG_STAGE,"start <%2.2lf, %2.2lf, %2.2lf>, end <%2.2lf, %2.2lf, %2.2lf>\n", start_pos[X], start_pos[Y], start_pos[Z], end_pos[X], end_pos[Y], end_pos[Z]); v3_scale(dist, 0.5, look); v3_add(start_pos, look, look); v3_normalize(dist, unit_dir); theta_xz = atan(unit_dir[Z] / unit_dir[X]); glPushMatrix(); glLoadIdentity(); glTranslated(start_pos[X], start_pos[Y], start_pos[Z]); glRotated( theta_xz * RadianToDegree, 0, 1, 0); glTranslated(dist[X]/1.5, dist[Y]/1.5, dist[Z]/1.5); // 1.5 to be safe to try to cover entire scene glGetDoublev(GL_MODELVIEW_MATRIX, model_mat); glPopMatrix(); eye_v4[Z] = sqrt(dist[X]*dist[X] + dist[Z]*dist[Z]) * 2; glmat44_mult_vec41(model_mat, eye_v4, eye_v4); eye[X] = eye_v4[X]; eye[Y] = eye_v4[Y]; eye[Z] = eye_v4[Z]; } /* changes look and eye given time, follow_theta, follow_phi, follow_lag, and pos and rot at the time */ double prev_eye[]= {0, 0, 0}; // eye pos in prev frame void Gl_Win::camera_follow(int time, double look[3], double eye[3]) { int frame_size_inDouble = rot_cnt * 3; double *pos = trans + time * 3; double *rot = euler + time * frame_size_inDouble; double rot_y_this_frame = rot[2]; // fig's facing direction double theta; double phi; double new_eye[3]; double eye_diff[3]; look[X] = pos[X]; look[Y] = pos[Y]; look[Z] = pos[Z]; if (rot_y_this_frame < 0) theta = (rot_y_this_frame + follow_theta) * DegreeToRadian; else theta = (180 - rot_y_this_frame - follow_theta) * DegreeToRadian; phi = follow_phi * DegreeToRadian; new_eye[X] = look[X] - follow_lag * sin(theta) * cos(phi); new_eye[Y] = look[Y] + follow_lag * sin(phi); new_eye[Z] = look[Z] + follow_lag * cos(theta) * cos(phi); // for smooth camera mvt from frame to frame v3_sub(new_eye, prev_eye, eye_diff); // get diff bw this and last frame v3_scale(eye_diff, FOLLOW_WT, eye_diff); // take weighted diff v3_add(eye_diff, prev_eye, eye); // get new eye v3_assign(prev_eye, eye); mdebug(DEBUG_STAGE,"t=%d, rot = %2.2lf, the=%2.2lf, phi=%2.2lf\n", time, rot[2], follow_theta, follow_phi); } void adjust_follow_theta(int mouseDragXdist, double &follow_theta) { double amt = mouseDragXdist / 100.0f; follow_theta += amt; if (follow_theta > 360) follow_theta = 360; if (follow_theta < 0) follow_theta = 0; mdebug(DEBUG_STAGE,"theta = %2.2lf, amt=%2.2lf\n", follow_theta, amt); } void adjust_follow_phi(int mouseDragYdist, double &follow_phi) { double amt = -mouseDragYdist / 100.0f; // neg 'cause scrn pos flips w/ gl. follow_phi += amt ; if (follow_phi > 90) follow_phi = 90; if (follow_phi < 0) follow_phi = 0; mdebug(DEBUG_STAGE,"phi = %2.2lf, amt=%2.2lf\n", follow_phi, amt); } void adjust_follow_lag(int mouseDragXdist, double &follow_lag) { double amt = mouseDragXdist / 100.0f; follow_lag += amt; mdebug(DEBUG_STAGE,"lag = %2.2lf, amt=%2.2lf\n", follow_lag, amt); } ////////light and shadow ///////////// /* a shadow matrix multiplied onto the stack according to light pos point drop shade matrix pm=[ly -lx 0 0 0 0 0 0 0 -lz ly 0 0 -1 0 ly] */ void Gl_Win::shadowMatrix(GLfloat light0_position[3]) { double pm[16] = {light0_position[1], 0, 0, 0, -light0_position[0], 0 , -light0_position[2], -1, 0, 0, light0_position[1], 0, 0, 0, 0, light0_position[1] }; glMultMatrixd(pm); } // try to set the light at center of the action and 100 above. void Gl_Win::light_pos(int frame_cnt, double *trans, GLfloat light0_position[3]) { double *start_pos = trans; double *end_pos = trans + (frame_cnt-1) * 3; double dist[3]; double d_light_pos[3]; v3_sub(end_pos, start_pos, dist); v3_scale(dist, 0.5, dist); v3_add(start_pos, dist, d_light_pos); light0_position[X] = (GLfloat) d_light_pos[X]; light0_position[Y] = (GLfloat) d_light_pos[Y] + 100; light0_position[Z] = (GLfloat) d_light_pos[Z]; } // bulb slightly below light source, so get lit void Gl_Win::draw_light_bulb(bool light, GLfloat light0_position[3]) { if (light) { mat_diffuse_ambient[R] = 1; mat_diffuse_ambient[G] = 0.2f; mat_diffuse_ambient[B] = 0; glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_diffuse_ambient); } else glColor3d(1, 0.2, 0); glPushMatrix(); glTranslatef(light0_position[X], light0_position[Y] - 10, light0_position[Z]); glRotatef(90, 1, 0, 0); gluCylinder(qobj, 0.5, 5, 6, 5, 1); glPopMatrix(); } // this is a spot light GLfloat light1_ambient[] = {1, 0.2f, 0.2f, 1.0}; GLfloat light1_diffuse[] = {0.2f, 0.2f, 0.2f, 1.0}; GLfloat light1_specular[] = {1.0, 1.0, 1.0, 1.0}; GLfloat light1_positon[] = { 0, 50, 0, 1}; GLfloat spot_direction[] = {0, 0, -1}; void set_light1( double pos[3], double spot_dir[3] ) { /* spot_direction[0] = (float) spot_dir[0]; spot_direction[1] = (float) spot_dir[1]; spot_direction[2] = (float) spot_dir[2]; light1_positon[0] = (float) pos[0] ; light1_positon[1] = (float) pos[1] ; light1_positon[2] = (float) pos[2]; */ glLightfv(GL_LIGHT1, GL_AMBIENT, light1_ambient); glLightfv(GL_LIGHT1, GL_DIFFUSE, light1_diffuse); glLightfv(GL_LIGHT1, GL_SPECULAR, light1_specular); glLightfv(GL_LIGHT1, GL_POSITION, light1_positon); glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, 1.5); glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, 0.5); glLightf(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, 0.2f); glLightf(GL_LIGHT1, GL_SPOT_CUTOFF, 45.0); glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, spot_direction); glLightf(GL_LIGHT1, GL_SPOT_EXPONENT, 2.0); glEnable(GL_LIGHT1); } // lighting button cb void lightCB(Fl_Widget* wid, Fl_Widget *container) { Fl_Light_Button *but = (Fl_Light_Button *)wid; Gl_Win *win = (Gl_Win *)container; if (but->value() == 1) win->light = true; else win->light = false; win->damage(1); } // floor button cb void floorCB(Fl_Widget* wid, Fl_Widget *container) { Fl_Light_Button *but = (Fl_Light_Button *)wid; Gl_Win *win = (Gl_Win *)container; if (but->value() == 1) win->b_floor = true; else win->b_floor = false; win->damage(1); }