// copyright Min Zhong, cs838 proj2, April, 2000 #include "viewer.h" #include "RunButton.h" #include "Marker.h" // vector v2 = glmat * v1, glmat is a col major mat void glmat44_mult_vec41(double *mat, double *v1, double *v2) { for (int i=0; i<4; i++) v2[i] = mat[i]*v1[0] + mat[i+4]*v1[1] + mat[i+8]*v1[2] + mat[i+12]*v1[3]; } // curtesy of gleicher's code // a quick and dirty hack for rotating the eyepoint // note: although this is modeled after the virtual sphere, its // much simple and (probably) not as good // it takes a lookat/eye pair and moves the eye around the lookat point // based on some wierd notions of how far to go, given how far the mouse moved // from the beginning // the fundamental flaw of this method is that it rotates around fixed axes // so, in a way, its instructive to use it to learn about gimbal lock // I often find that I cannot rotate the world the way that i want with this // interface void orbit(int mx, int my, double lx, double ly, double lz, double ex, double ey, double ez, double& rx, double& ry, double& rz) { // // first - if the mouse motion is small, return to starting position // this should make it easier to move around 1 axis if (mx<0) { mx = mx+5; if (mx>0) mx = 0; } else { mx = mx-5; if (mx<0) mx = 0; } if (my<0) { my = my+5; if (my>0) my = 0; } else { mx = mx-5; if (my<0) my = 0; } // make the center of the coordinate system be the lookat point so that's // where we rotate about ex -= lx; ey -= ly; ez -= lz; // horizontal motions rotate around the vertical (y axis) by an amount // proportional to the amount the mouse moved - the amount is pretty // arbitrary double hz = ((double) mx) / 200; double sx = sin(hz); double cx = cos(hz); rx = cx * ex - sx * ez; rz = sx * ex + cx * ez; // note: rotating around the z (or x) axis isn't really right, but its // easy double vt = ((double) my) / 200; double sz = sin(vt); double cz = cos(vt); ex = rx; // for safe keeping rx = cz * ex - sz * ey; ry = sz * ex + cz * ey; // shift the result back so that the lookat point is in the right place rx += lx; ry += ly; rz += lz; } // the guts of the slider - void runSliderCB(Fl_Widget* in_slider, Fl_Widget* in_wind) { RunSlider *slider = (RunSlider *)in_slider; Panel *wind = (Panel *)in_wind; wind->key_addB->value(0); wind->key_rmvB->value(0); wind->gl->damage(1); } // switch bw real time and const spd play back void play_modeCB(Fl_Widget* wid, Fl_Widget *container) { RunButton *but = (RunButton *)wid; Gl_Win *win = (Gl_Win *)container; if (win->play_mode == REAL_TIME) { win->play_mode = CONST_SPD; but->value(0); } else if (win->play_mode == CONST_SPD) { win->play_mode = REAL_TIME; but->value(1); } win->runBut->init_ticks(win->frame_time, win->play_mode); win->damage(1); } // remove all keys void key_clearCB(Fl_Widget* wid, Fl_Widget *container) { Fl_Round_Button *but = (Fl_Round_Button *)wid; Panel *wind = (Panel *)container; Gl_Win *gl = wind->gl; but->value(1); gl->key_cnt = 0; // set key cnt to 0 if (gl->e_interpType != HIDE && gl->e_interpType != NONE) gl->e_interpType = HIDE; wind->euler_browser->value(HIDE); if (gl->q_interpType != HIDE && gl->q_interpType != NONE) gl->q_interpType = HIDE; wind->quat_browser->value(HIDE); if (gl->m_interpType != HIDE && gl->m_interpType != NONE) gl->m_interpType = HIDE; wind->emap_browser->value(HIDE); but->value(0); wind->damage(1); } // print all keys void key_printCB(Fl_Widget* wid, Fl_Widget *container) { Fl_Round_Button *but = (Fl_Round_Button *)wid; Gl_Win *win = (Gl_Win *)container; but->value(1); win->disp_keyTimes(); but->value(0); } // key the frame slider is at void key_addCB(Fl_Widget* wid, Fl_Widget *container) { Fl_Round_Button *but = (Fl_Round_Button *)wid; Panel *wind = (Panel *)container; Gl_Win *gl = wind->gl; if (gl->keyTimes == NULL) { fl_alert("Load Motion file first."); but->value(0); } else { but->value(1); if ( gl->key_add((int) gl->timeS->value()) == SUCCESS ) { wind->key_rmvB->value(0); // turn off remove but if it were on at that frame wind->damage(1); } } } // remove this key void key_rmvCB(Fl_Widget* wid, Fl_Widget *container) { Fl_Round_Button *but = (Fl_Round_Button *)wid; Panel *wind = (Panel *)container; Gl_Win *gl = wind->gl; if (gl->keyTimes == NULL) { fl_alert("Load Motion file first."); but->value(0); } else { but->value(1); if ( gl->key_remove((int) gl->timeS->value()) == SUCCESS ) { wind->key_addB->value(0); // turn off the key_add but if (gl->key_cnt == 0) { // no interp allowed if no key if (gl->e_interpType != HIDE && gl->e_interpType != NONE) gl->e_interpType = HIDE; wind->euler_browser->value(HIDE); if (gl->q_interpType != HIDE && gl->q_interpType != NONE) gl->q_interpType = HIDE; wind->quat_browser->value(HIDE); if (gl->m_interpType != HIDE && gl->m_interpType != NONE) gl->m_interpType = HIDE; wind->emap_browser->value(HIDE); } wind->damage(1); } else { fl_alert("This frame was not keyed."); } } } // sets up gl_win's keytimes array to key every nth frame. void key_nthCB(Fl_Widget* wid, Fl_Widget *container) { Fl_Int_Input *but = (Fl_Int_Input *)wid; Panel *win = (Panel *)container; int nth = atoi( but->value() ); if (win->gl->keyTimes == NULL) { fl_alert("Load Motion file first."); but->value(0); } else if (nth >= win->gl->frame_cnt || nth <= 0 ) fl_alert("invalid nth frame. Range: [1, %d]", win->gl->frame_cnt-1 ); else if (win->gl->key_nth( nth ) == SUCCESS) win->damage(1); } // begin frame button cb void beginCB(Fl_Widget* wid, Fl_Widget *container) { Fl_Int_Input *but = (Fl_Int_Input *)wid; Gl_Win *win = (Gl_Win *)container; int new_begin = atoi( but->value() ); char s_old_begin[10]; if (new_begin == win->begin || new_begin < 0 ) {// no change fl_alert("invalid beginning. Range: [0, %d]", win->frame_cnt-1 ); // reset to old val _itoa(win->begin, s_old_begin, 10); but->value(s_old_begin); return; } win->begin = new_begin; win->timeS->range(new_begin, win->end); win->timeS->minimum(new_begin); win->runBut->init_ticks(win->frame_time, win->play_mode); } // end frame button cb void endCB(Fl_Widget* wid, Fl_Widget *container) { Fl_Int_Input *but = (Fl_Int_Input *)wid; Gl_Win *win = (Gl_Win *)container; int new_end = atoi( but->value() ); char s_old_end[10]; if (new_end == win->end || new_end >= win->frame_cnt ) {// no change fl_alert("invalid end. Range: [0, %d]", win->frame_cnt-1 ); // reset to old val _itoa(win->end, s_old_end, 10); but->value(s_old_end); return; } win->end = new_end; win->timeS->range(win->begin, new_end); win->timeS->maximum(new_end); win->runBut->init_ticks(win->frame_time, win->play_mode); } // open input file button callback void in_motion_fileCB(Fl_Widget* wid, Fl_Widget *container) { char s_val[10]; Fl_Button *but = (Fl_Button *)wid; Panel *win = (Panel *)container; Gl_Win *gl = win->gl; gl->read_input_file(win); if (gl->b_readSuceed) { _itoa(0, s_val, 10); win->key_nthB->value(s_val); win->emap_browser->value(HIDE); win->euler_browser->value(NONE); win->quat_browser->value(NONE); win->damage(1); } else fl_alert("invalid motion file.\n"); } // load marker request file void in_marker_fileCB(Fl_Widget* wid, Fl_Widget *container) { Fl_Button *but = (Fl_Button *)wid; Gl_Win *win = (Gl_Win *)container; if (win->cap == NULL) { fl_alert("Load Motion file first."); } else if (win->read_marker_request(win->marker_head) == SUCCESS) { if (win->calc_markers_pos(win->marker_head, win->m_rotType) == SUCCESS) win->damage(1); else fl_alert("Invalid Joint in marker file."); } } // write marker coord to file void out_marker_fileCB(Fl_Widget* wid, Fl_Widget *container) { Fl_Button *but = (Fl_Button *)wid; Gl_Win *win = (Gl_Win *)container; if (win->cap == NULL) { fl_alert("Load Motion file first."); } else win->export_markers(win->marker_head); } // choose whether and how to show markers (which rotation to use) void marker_rotType_browserCB(Fl_Widget* wid, Fl_Widget *container) { Fl_Hold_Browser *b = (Fl_Hold_Browser *)wid; Gl_Win *win = (Gl_Win *)container; RotType old_m = win->m_rotType; switch (b->value()) { case 1: win->m_rotType = EULER; break; case 2: win->m_rotType = QUAT; break; case 3: win->m_rotType = EXPMAP; break; default: return; } if (win->m_rotType != old_m) { win->calc_markers_pos(win->marker_endsite, win->m_rotType); // recalc for all endsites if (win->marker_head != NULL) if (win->calc_markers_pos(win->marker_head, win->m_rotType) != SUCCESS) fl_alert("Invalid Joint in marker file."); // should't happen win->damage(1); } } // choose euler interp options and invoke appropriate interp routine void euler_browserCB(Fl_Widget* wid, Fl_Widget *container) { Fl_Hold_Browser *b = (Fl_Hold_Browser *)wid; Gl_Win *win = (Gl_Win *)container; InterpType old_interp = win->e_interpType; switch (b->value()) { case 1: win->e_interpType = HIDE; break; case 2: win->e_interpType = NONE; break; case 3: if (win->key_cnt < 2) { fl_alert("set more keys first."); b->value(old_interp); return; } else { win->e_interpType = LINEAR; if (old_interp != win->e_interpType ) win->b_need_reinterp = true; } break; case 4: if (win->key_cnt < 4) { fl_alert("set more keys first."); b->value(old_interp); return; } else { win->e_interpType = CARDINAL; if (old_interp != win->e_interpType ) win->b_need_reinterp = true; } break; default: return; } if (old_interp != HIDE && old_interp != NONE && (win->e_interpType == NONE || win->e_interpType == HIDE) && win->m_rotType == EULER) { // going from interp ->non-interp win->calc_markers_pos(win->marker_endsite, EULER); if (win->marker_head != NULL) win->calc_markers_pos(win->marker_head, EULER); } win->damage(1); } // choose quat interp options and invoke appropriate interp routine void quat_browserCB(Fl_Widget* wid, Fl_Widget *container) { Fl_Hold_Browser *b = (Fl_Hold_Browser *)wid; Gl_Win *win = (Gl_Win *)container; InterpType old_interp = win->q_interpType; switch (b->value()) { case 1: win->q_interpType = HIDE; break; case 2: win->q_interpType = NONE; break; case 3: if (win->key_cnt < 2) { fl_alert("set more keys first."); b->value(old_interp); return; } else { win->q_interpType = SLERP; if (old_interp != win->q_interpType ) win->b_need_reinterp = true; } break; case 4: if (win->key_cnt < 4) { fl_alert("set more keys first."); b->value(old_interp); return; } else { win->q_interpType = Q_BERZIER; if (old_interp != win->q_interpType ) win->b_need_reinterp = true; } break; default: return; } if (old_interp != HIDE && old_interp != NONE && (win->q_interpType == NONE || win->q_interpType == HIDE) && win->m_rotType == QUAT) { // going from interp ->non-interp win->calc_markers_pos(win->marker_endsite, QUAT); if (win->marker_head != NULL) win->calc_markers_pos(win->marker_head, QUAT); } win->damage(1); } // choose exp map interp options and invoke appropriate interp routine void emap_browserCB(Fl_Widget* wid, Fl_Widget *container) { Fl_Hold_Browser *b = (Fl_Hold_Browser *)wid; Gl_Win *win = (Gl_Win *)container; InterpType old_interp = win->m_interpType; switch (b->value()) { case 1: win->m_interpType = HIDE; break; case 2: win->m_interpType = NONE; break; case 3: if (win->key_cnt < 2) { fl_alert("set more keys first."); b->value(old_interp); return; } else { win->m_interpType = EM_SLERP; if (old_interp != win->m_interpType ) win->b_need_reinterp = true; } break; case 4: if (win->key_cnt < 2) { fl_alert("set more keys first."); b->value(old_interp); return; } else { win->m_interpType = EM_LIN; if (old_interp != win->m_interpType ) win->b_need_reinterp = true; } break; case 5: if (win->key_cnt < 4) { fl_alert("set more keys first."); b->value(old_interp); return; } else { win->m_interpType = CARDINAL; if (old_interp != win->m_interpType ) win->b_need_reinterp = true; } break; default: return; } if (old_interp != HIDE && old_interp != NONE && (win->m_interpType == NONE || win->m_interpType == HIDE) && win->m_rotType == EXPMAP) { // going from interp ->non-interp win->calc_markers_pos(win->marker_endsite, EXPMAP); if (win->marker_head != NULL) win->calc_markers_pos(win->marker_head, EXPMAP); } win->damage(1); } // sel camera view void camera_browserCB(Fl_Widget* wid, Fl_Widget *container) { Fl_Hold_Browser *b = (Fl_Hold_Browser *)wid; Gl_Win *win = (Gl_Win *)container; switch( b->value() ) { case OMIN: win->cameraView = OMIN; break; case FOLLOW: if ( win->cap == NULL ) { // no motion file loaded fl_alert("Load Motion file first."); b->value(OMIN); return; } else win->cameraView = FOLLOW; break; default: return; } win->damage(1); } // sel markers to be drawn void marker_sel_browserCB(Fl_Widget* wid, Fl_Widget *container) { Fl_Multi_Browser *b = (Fl_Multi_Browser *)wid; Gl_Win *win = (Gl_Win *)container; int cnt = b->size(); for (int i=1; i<=cnt; i++) { if (b->selected(i)) (win->endsites_draw)[i-1].b_draw = true; else (win->endsites_draw)[i-1].b_draw = false; } win->damage(1); }