OpenGL in FLTK Tutorial by Xu

advertisement
FLUID

The Fast Light User Interface Designer, or FLUID, is a graphical editor that is
used to produce FLTK source code

Creates C++ code

Compile .fl file into .cxx and .h

Located in fltk-source/fluid/fluidd.exe

We will create the CustomWidget using fluid
Timers
•
•
Not 100% accurate (don't measure time with them)
Single shot timeouts
•
void add_timeout(double t, Fl_Timeout_Handler, void* d)
o call a function in t seconds
void remove_timeout(Fl_Timeout_Handler, void* d)
o cancels a timeout (harmless if timer already triggered)
void repeat_timeout(double t, Fl_Timeout_Handler, void* d)
o call a function t seconds after the last timeout triggered
o can only be called from within a timer callback
•
•
Simple Timer
Print "TICK" every second
void callback(void*)
{
printf(“TICK\n");
Fl::repeat_timeout(1.0, callback);
}
int main()
{
……
Fl::add_timeout(1.0, callback);
return Fl::run()
}
Add Timer to Move CustomWidget
Goal: Have slider slide back and forth
•
Use globals for all variables and widgets
o Make customWidget global
o Add variable to control direction
• Callback
o Setup repeat timer
o Move widget in specified direction
o Check if we have reached max or min and
change direction
• Main
o Set initial direction
o Initial timer call
int increasing;
CustomWidget *customWidget;
void timer(void*)
{
Fl::repeat_timeout(0.02, timer);
if ( increasing )
{
customWidget->value(customWidget->value() + 1);
if ( customWidget->value() >= customWidget->maximum() )
increasing = 0;
}
else
{
customWidget->value(customWidget->value() - 1);
if ( customWidget->value() <= customWidget->minimum() )
increasing = 1;
}
}
Idle
•
•
Similar to GLUT
add_idle(void (*cb)(void*), void *)
o function to call whenever nothing else is
happening
o can have multiple callbacks
• remove_timout(void (*cb)(void*), void *)
o removes callback function if it exists
OpenGL in FLTK
OpenGL Widget
Create a subclass of Fl_Gl_Window
o #include <FL/Fl_Gl_Window.H>
o #include <FL/gl.h>
 Will include <GL/gl.h>
• Need to implement draw function in subclass
o Setup view port
 valid() will return false if needed
o 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
o 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
•
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);
•
Need to tell FLTK/OpenGL Widget to update
o 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;
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();
}
}
•
Events
Implement int handle(int event)
o event is mouse click & drag, mouse wheel,
keyboard presses & release, system events
• Return 1 if event is used
o Event consumed
• Return 0 is unused
o Event will continue to be passed around
• Additional helper functions
o Mouse: event_button() event_x()
o Keyboard: event_key()
•
Spin Triangle with Mouse
•
•
Goal: mouse drags will rotate object
Filter out only used event
o 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);
•
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);
}
Assignment 1 Part 3 in FLUID

Keep class OpenGLWindow

In fluidd.exe

Add New->Code->class, set the name of the class ‘UI’

Highlight class UI, New->Code->function/Method, add the constructor UI(), set it
public

Highlight UI(), New->group->Window, under C++ tab, name it mainWindow

Highlight mainWindow, New->valuator->Slider. Change its label. Under tab C++, set
it horizontal. Add extra code


divisions->range(0, 5);

divisions->step(1);
Add callback

glWindow->setDivision(divisions->value());

glWindow->redraw();


Highlight mainWindow

New->Buttons->button. Change its label. Under tab C++, set it a toggle button, and
set its name spinning.

New->others->box to add OpenGLWindow widget. Under tab C++, add extra code:
#include"OpenGLWindow.h“ and name it glWindow.
Highlight class UI

New->Code->declaration, add a variable ‘float spin’
Download