190 likes | 561 Views
OpenGL in FLTK. Timers. Not 100% accurate (don't measure time with them) Single shot timeouts void add_timeout(double t, Fl_Timeout_Handler, void* d) call a function in t seconds void remove_timeout(Fl_Timeout_Handler, void* d) cancels a timeout (harmless if timer already triggered)
E N D
Timers • Not 100% accurate (don't measure time with them) • Single shot timeouts • void add_timeout(double t, Fl_Timeout_Handler, void* d) • call a function in t seconds • void remove_timeout(Fl_Timeout_Handler, void* d) • cancels a timeout (harmless if timer already triggered) • void repeat_timeout(double t, Fl_Timeout_Handler, void* d) • call a function t seconds after the last timeout triggered • can only be called from within a timer callback
Simple Timer • Print "TICK" every second void callback(void*) { printf("PUTS"); Fl::repeat_timeout(1.0, callback); } int main() { Fl::add_timeout(1.0, callback); return Fl::run() }
Add Timer to Move Out CustomWidget Goal: Have slider slide back and forth • Use globals for all variables and widgets • Make customWidget global • Add variable to control direction • Callback • Setup repeat timer • Move widget in specified direction • Check if we have reached max or min and change direction • Main • Set initial direction • Initial timer call
Idle • Similar to GLUT • add_idle(void (*cb)(void*), void *) • function to call whenever nothing else is happening • can have multiple callbacks • remove_timout(void (*cb)(void*), void *) • removes callback function if it exists
OpenGL Widget • Create a subclass of Fl_Gl_Window • #include <FL/Fl_Gl_Window.H> • #include <FL/gl.h> • Will include <GL/gl.h> • Need to implement draw function in subclass • Setup view port • valid() will return false if needed • Actual drawing
OpenGL Widget class OpenGLWindow : public Fl_Gl_Window {private: void draw() { if ( !valid() ) { // initialization } // draw };public: OpenGLWindow(int x, int y, int w, int h, const char* l = 0) : Fl_Gl_Window(x, y, w, h, l) { }; };
3D Gasket in FLTK • Put all code into subclass of Fl_Gl_Window • Copy triangle, tetra, and divide_tetra functions • Move colors into tetra and v into draw • All reference to width are height need to be replaced with w() and h() • Hard code number of sub divisions • Create a window and place OpenGL widget in it
Widget to Control Sub Divisions • Recommendation: make all widgets global • OpenGL draw() now get value from slider widget • divide_tetra(v[0], v[1], v[2], v[3], • divisions->value()); • Add a slider (and label) for number of sub divisions divisions = new Fl_Slider(100, 480, 540, 20); divisions->type(FL_HORIZONTAL); divisions->range(1, 20); divisions->step(1);
Widget to Control Sub Divisions • Need to tell FLTK/OpenGL Widget to update • call widget's redraw() • Need to redraw when we change slider (callback) void update(Fl_Widget*, void*){ glwindow->redraw();} // when creating slider divisions->callback(update);
Assignment 1 Part 3 in FLTK • Will use toggle button instead of mouse clicks • Timer instead of idle • Create toggle button and start timer • spinning = new Fl_Button(545, 485, 90, 20, • "Spinning"); • spinning->type(FL_TOGGLE_BUTTON); • Fl::add_timeout(1, timer, 0); • spin = 0.0f;
Assignment 1 Part 3 in FLTK • Update spin and redraw if necessary void timer(void*){ Fl::repeat_timeout(0.02, timer); if ( spinning->value() ) { spin += 1.0f; if ( spin > 360.0f ) spin -= 360.0f; glwindow->redraw(); }}
Assignment 1 Part 3 in FLTK • Add spin to OpenGL widget extern float spin; • Rotate before drawing (before glBegin) glLoadIdentity(); glRotatef(spin, 0.0f, 1.0f, 0.0f);
Events • Implement int handle(int event) • event is mouse click & drag, mouse wheel, keyboard presses & release, system events • Return 1 if event use • Event consumed • Return 0 is unesed • Event will continue to be passed around • Additional helper functions • Mouse: event_button() event_x() • Keyboard: event_key()
Spin Triangle with Mouse • Goal: mouse drags will rotate object • Filter out only used event • Pass rest to default handler • No previous mouse position with drag event (only current) • Initial click will seed last position • Need to hold current state
Spin Triangle with Mouse • Header: int oldX, oldY; float vRotation, hRotation; int handle(int event); • Constructor: vRotation = hRotation = 0.0f; • Draw: glRotatef(hRotation, 0.0f, 1.0f, 0.0f); glRotatef(vRotation, 1.0f, 0.0f, 0.0f);
Spin Triangle with Mouse • Handle switch ( event ) { case FL_DRAG: hRotation += Fl::event_x() - oldX; vRotation += Fl::event_y() - oldY; redraw(); case FL_PUSH: oldX = Fl::event_x(); oldY = Fl::event_y(); return 1; default: return Fl_Gl_Window::handle(event); }