diff options
| author | Albrecht Schlosser <albrechts.fltk@online.de> | 2008-09-13 15:55:32 +0000 |
|---|---|---|
| committer | Albrecht Schlosser <albrechts.fltk@online.de> | 2008-09-13 15:55:32 +0000 |
| commit | 8416a4012ecb985d150fad566659cf59ee1dc3aa (patch) | |
| tree | a0b52461eeeaf926de99392145c087e96f6c36e1 /documentation/opengl.dox | |
| parent | 054d25081a74d504eb38042ffbd9acf70be4de1d (diff) | |
Doxygen documentation - WP12 and WP13 - first step.
Converted the descriptive chapters of the html docs to doxygen format
and modified index.dox accordingly.
This checkin includes only trivial reformatting, no major rewriting.
Added a chapter "Migrating Code from FLTK 1.1 to 1.3".
All links on the main page are working now.
Todo:
- Check doxygen error messages, rewrite pages (html tags, contents).
- Fill the new "Migrating..." chapter.
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@6224 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
Diffstat (limited to 'documentation/opengl.dox')
| -rw-r--r-- | documentation/opengl.dox | 463 |
1 files changed, 463 insertions, 0 deletions
diff --git a/documentation/opengl.dox b/documentation/opengl.dox new file mode 100644 index 000000000..87a5c50c2 --- /dev/null +++ b/documentation/opengl.dox @@ -0,0 +1,463 @@ +/** + + \page opengl 8 - Using OpenGL + +<P>This chapter discusses using FLTK for your OpenGL applications. + +<H2>Using OpenGL in FLTK</H2> + +<P>The easiest way to make an OpenGL display is to subclass <A +href="Fl_Gl_Window.html#Fl_Gl_Window"><TT>Fl_Gl_Window</TT></A>. +Your subclass must implement a <TT>draw()</TT> method which uses +OpenGL calls to draw the display. Your main program should call +<TT>redraw()</TT> when the display needs to change, and +(somewhat later) FLTK will call <TT>draw()</TT>. + +<P>With a bit of care you can also use OpenGL to draw into +normal FLTK windows. This allows you to use Gouraud shading for +drawing your widgets. To do this you use the <A +href="#gl_start"><TT>gl_start()</TT></A> and <A +href=#gl_finish><TT>gl_finish()</TT></A> functions around your +OpenGL code.</P> + +<P>You must include FLTK's <TT><FL/gl.h></TT> header +file. It will include the file <TT><GL/gl.h></TT>, define +some extra drawing functions provided by FLTK, and include the +<TT><windows.h></TT> header file needed by WIN32 +applications.</P> + +<H2>Making a Subclass of Fl_Gl_Window</H2> + +<P>To make a subclass of Fl_Gl_Window, you must provide: + +<UL> + + <LI>A class definition.</LI> + + <LI>A <TT>draw()</TT> method.</LI> + + <LI>A <TT>handle()</TT> method if you need to receive + input from the user.</LI> + +</UL> + +<P>If your subclass provides static controls in the window, they +must be redrawn whenever the <tt>FL_DAMAGE_ALL</tt> bit is set +in the value returned by <tt>damage()</tt>. For double-buffered +windows you will need to surround the drawing code with the +following code to make sure that both buffers are redrawn: + +<UL><PRE> +#ifndef MESA +glDrawBuffer(GL_FRONT_AND_BACK); +#endif // !MESA +... draw stuff here ... +#ifndef MESA +glDrawBuffer(GL_BACK); +#endif // !MESA +</PRE></UL> + +<CENTER><TABLE WIDTH="80%" BORDER="1" CELLPADDING="5" CELLSPACING="0" BGCOLOR="#cccccc"> +<TR> + <TD><B>Note:</B> + + <P>If you are using the Mesa graphics library, the call + to <tt>glDrawBuffer()</tt> is not required and will slow + down drawing considerably. The preprocessor instructions + shown above will optimize your code based upon the + graphics library used. + + </TD> + +</TR> +</TABLE></CENTER> + +<H3>Defining the Subclass</H3> + +<P>To define the subclass you just subclass the +<TT>Fl_Gl_Window</TT> class: + +<UL><PRE> +class MyWindow : public Fl_Gl_Window { + void draw(); + int handle(int); + +public: + MyWindow(int X, int Y, int W, int H, const char *L) + : Fl_Gl_Window(X, Y, W, H, L) {} +}; +</PRE></UL> + +<P>The <TT>draw()</TT> and <TT>handle()</TT> methods are +described below. Like any widget, you can include additional +private and public data in your class (such as scene graph +information, etc.) + +<H3>The draw() Method</H3> + +<P>The <TT>draw()</TT> method is where you actually do your +OpenGL drawing: + +<UL><PRE> +void MyWindow::draw() { + if (!valid()) { + ... set up projection, viewport, etc ... + ... window size is in w() and h(). + ... valid() is turned on by FLTK after draw() returns + } + ... draw ... +} +</PRE></UL> + +<H3>The handle() Method</H3> + +<P>The <TT>handle()</TT> method handles mouse and keyboard +events for the window: + +<UL><PRE> +int MyWindow::handle(int event) { + switch(event) { + case FL_PUSH: + ... mouse down event ... + ... position in Fl::event_x() and Fl::event_y() + return 1; + case FL_DRAG: + ... mouse moved while down event ... + return 1; + case FL_RELEASE: + ... mouse up event ... + return 1; + case FL_FOCUS : + case FL_UNFOCUS : + ... Return 1 if you want keyboard events, 0 otherwise + return 1; + case FL_KEYBOARD: + ... keypress, key is in Fl::event_key(), ascii in Fl::event_text() + ... Return 1 if you understand/use the keyboard event, 0 otherwise... + return 1; + case FL_SHORTCUT: + ... shortcut, key is in Fl::event_key(), ascii in Fl::event_text() + ... Return 1 if you understand/use the shortcut event, 0 otherwise... + return 1; + default: + // pass other events to the base class... + return Fl_Gl_Window::handle(event); + } +} +</PRE></UL> + +<P>When <TT>handle()</TT> is called, the OpenGL context is not +set up! If your display changes, you should call +<TT>redraw()</TT> and let <TT>draw()</TT> do the work. Don't +call any OpenGL drawing functions from inside <TT>handle()</TT>! + +<P>You can call <I>some</I> OpenGL stuff like hit detection and texture +loading functions by doing: </P> + +<UL><PRE> + case FL_PUSH: + make_current(); // make OpenGL context current + if (!valid()) { + ... set up projection exactly the same as draw ... + valid(1); // stop it from doing this next time + } + ... ok to call NON-DRAWING OpenGL code here, such as hit + detection, loading textures, etc... +</PRE></UL> + +<P>Your main program can now create one of your windows by doing +<TT>new MyWindow(...)</TT>. You can also use <A +href="fluid.html#FLUID">FLUID</A> by: + +<OL> + + <LI>Putting your class definition in a + <tt>MyWindow.H</tt> file.</LI> + + <LI>Creating a <tt>Fl_Box</tt> widget in FLUID.</LI> + + <LI>In the widget panel fill in the "class" + field with <tt>MyWindow</tt>. This will make FLUID + produce constructors for your new class.</LI> + + <LI>In the "Extra Code" field put <TT>#include + "MyWindow.H"</TT>, so that the FLUID output + file will compile.</LI> + +</OL> + +<P>You must put <TT>glwindow->show()</TT> in your main code +after calling <TT>show()</TT> on the window containing the +OpenGL window. + +<H2>Using OpenGL in Normal FLTK Windows</H2> + +<P>You can put OpenGL code into an <A +href="subclassing.html#draw"><TT>Fl_Widget::draw()</TT></A> +method or into the code for a <A +href="common.html#boxtypes">boxtype</A> or other places with some +care. + +<P>Most importantly, before you show <I>any</I> windows, +including those that don't have OpenGL drawing, you <B>must</B> +initialize FLTK so that it knows it is going to use OpenGL. You +may use any of the symbols described for <A +href="Fl_Gl_Window.html#Fl_Gl_Window.mode"><TT>Fl_Gl_Window::mode()</TT></A> +to describe how you intend to use OpenGL:</P> + +<UL><PRE> +Fl::gl_visual(FL_RGB); +</PRE></UL> + +<P>You can then put OpenGL drawing code anywhere you can draw +normally by surrounding it with: + +<UL><PRE> +gl_start(); +... put your OpenGL code here ... +gl_finish(); +</PRE></UL> + +<P><A name="gl_start"><TT>gl_start()</TT></A> and <A +name="gl_finish"><TT>gl_finish()</TT></A> set up an OpenGL +context with an orthographic projection so that 0,0 is the +lower-left corner of the window and each pixel is one unit. The +current clipping is reproduced with OpenGL <TT>glScissor()</TT> +commands. These functions also synchronize the OpenGL graphics stream +with the drawing done by other X, WIN32, or FLTK functions. + +<P>The same context is reused each time. If your code changes +the projection transformation or anything else you should use +<TT>glPushMatrix()</TT> and <TT>glPopMatrix()</TT> functions to +put the state back before calling <TT>gl_finish()</TT>.</P> + +<P>You may want to use <TT>Fl_Window::current()->h()</TT> to +get the drawable height so that you can flip the Y +coordinates.</P> + +<P>Unfortunately, there are a bunch of limitations you must +adhere to for maximum portability: </P> + +<UL> + + <LI>You must choose a default visual with <A + href="Fl.html#Fl.gl_visual"><TT>Fl::gl_visual()</TT></A>.</LI> + + <LI>You cannot pass <TT>FL_DOUBLE</TT> to + <TT>Fl::gl_visual()</TT>.</LI> + + <LI>You cannot use <TT>Fl_Double_Window</TT> or + <TT>Fl_Overlay_Window</TT>.</LI> + +</UL> + +<P>Do <I>not</I> call <TT>gl_start()</TT> or +<TT>gl_finish()</TT> when drawing into an <TT>Fl_Gl_Window</TT>! + +<H2>OpenGL Drawing Functions</H2> + +<P>FLTK provides some useful OpenGL drawing functions. They can +be freely mixed with any OpenGL calls, and are defined by +including <TT><FL/gl.H></TT> which you should include +instead of the OpenGL header <TT><GL/gl.h></TT>. + +<H4>void gl_color(Fl_Color)</H4> + +<P>Sets the current OpenGL color to a FLTK color. <I>For +color-index modes it will use <TT>fl_xpixel(c)</TT>, which is +only right if this window uses the default colormap!</I> + +<H4>void gl_rect(int x, int y, int w, int h) +<BR>void gl_rectf(int x, int y, int w, int h)</H4> + +<P>Outlines or fills a rectangle with the current color. If <A +HREF="Fl_Gl_Window.html#Fl_Gl_Window.ortho"><TT>Fl_Gl_Window::ortho()</TT></A> +has been called, then the rectangle will exactly fill the pixel +rectangle passed. + +<H4>void gl_font(Fl_Font fontid, int size)</H4> + +<P>Sets the current OpenGL font to the same font you get by +calling <A href="drawing.html#fl_font"><TT>fl_font()</TT></A>. + +<H4>int gl_height() +<BR>int gl_descent() +<BR>float gl_width(const char *) +<BR>float gl_width(const char *, int n) +<BR>float gl_width(uchar)</H4> + +<P>Returns information about the current OpenGL font. + +<H4>void gl_draw(const char *) +<BR>void gl_draw(const char *, int n)</H4> + +<P>Draws a nul-terminated string or an array of <TT>n</TT> +characters in the current OpenGL font at the current raster +position. + +<H4>void gl_draw(const char *, int x, int y) +<BR>void gl_draw(const char *, int n, int x, int y) +<BR>void gl_draw(const char *, float x, float y) +<BR>void gl_draw(const char *, int n, float x, float y)</H4> + +<P>Draws a nul-terminated string or an array of <TT>n</TT> +characters in the current OpenGL font at the given position. + +<H4>void gl_draw(const char *, int x, int y, int w, int h, Fl_Align)</H4> + +<P>Draws a string formatted into a box, with newlines and tabs +expanded, other control characters changed to ^X, and aligned +with the edges or center. Exactly the same output as <A +href="drawing.html#text"><TT>fl_draw()</TT></A>. + +<h2>Speeding up OpenGL</h2> + +<P>Performance of Fl_Gl_Window may be improved on some types of +OpenGL implementations, in particular MESA and other software +emulators, by setting the <tt>GL_SWAP_TYPE</tt> environment +variable. This variable declares what is in the backbuffer after +you do a swapbuffers. + +<ul> + + <li><tt>setenv GL_SWAP_TYPE COPY</tt> + + <p>This indicates that the back buffer is copied to the + front buffer, and still contains it's old data. This is + true of many hardware implementations. Setting this + will speed up emulation of overlays, and widgets that + can do partial update can take advantage of this as + damage() will not be cleared to -1. <p> + + <li><tt>setenv GL_SWAP_TYPE NODAMAGE</tt> + + <p>This indicates that nothing changes the back buffer + except drawing into it. This is true of MESA and Win32 + software emulation and perhaps some hardware emulation + on systems with lots of memory. <p> + + <li>All other values for <tt>GL_SWAP_TYPE</tt>, and not + setting the variable, cause FLTK to assume that the + back buffer must be completely redrawn after a swap. + +</ul> + +<p>This is easily tested by running the <TT>gl_overlay</TT> demo +program and seeing if the display is correct when you drag +another window over it or if you drag the window off the screen +and back on. You have to exit and run the program again for it +to see any changes to the environment variable. + +<H2>Using OpenGL Optimizer with FLTK</H2> + +<P><A href="http://www.sgi.com/software/optimizer">OpenGL +Optimizer</A> is a scene graph toolkit for OpenGL available from +Silicon Graphics for IRIX and Microsoft Windows. It allows you +to view large scenes without writing a lot of OpenGL code. + +<H4>OptimizerWindow Class Definition</H4> + +<P>To use OpenGL Optimizer with FLTK you'll need to create a +subclass of <TT>Fl_Gl_Widget</TT> that includes several state +variables: + +<UL><PRE> +class OptimizerWindow : public Fl_Gl_Window { + csContext *context_; // Initialized to 0 and set by draw()... + csDrawAction *draw_action_; // Draw action... + csGroup *scene_; // Scene to draw... + csCamara *camera_; // Viewport for scene... + + void draw(); + +public: + OptimizerWindow(int X, int Y, int W, int H, const char *L) + : Fl_Gl_Window(X, Y, W, H, L) { + context_ = (csContext *)0; + draw_action_ = (csDrawAction *)0; + scene_ = (csGroup *)0; + camera_ = (csCamera *)0; + } + + void scene(csGroup *g) { scene_ = g; redraw(); } + + void camera(csCamera *c) { + camera_ = c; + if (context_) { + draw_action_->setCamera(camera_); + camera_->draw(draw_action_); + redraw(); + } + } +}; +</PRE></UL> + +<H4>The camera() Method</H4> + +<P>The <TT>camera()</TT> method sets the camera (projection and +viewpoint) to use when drawing the scene. The scene is redrawn after +this call. + +<H4>The draw() Method</H4> + +<P>The <TT>draw()</TT> method performs the needed initialization and does +the actual drawing: + +<UL><PRE> +void OptimizerWindow::draw() { + if (!context_) { + // This is the first time we've been asked to draw; create the + // Optimizer context for the scene... + +#ifdef WIN32 + context_ = new csContext((HDC)fl_getHDC()); + context_->ref(); + context_->makeCurrent((HDC)fl_getHDC()); +#else + context_ = new csContext(fl_display, fl_visual); + context_->ref(); + context_->makeCurrent(fl_display, fl_window); +#endif // WIN32 + + ... perform other context setup as desired ... + + // Then create the draw action to handle drawing things... + + draw_action_ = new csDrawAction; + if (camera_) { + draw_action_->setCamera(camera_); + camera_->draw(draw_action_); + } + } else { +#ifdef WIN32 + context_->makeCurrent((HDC)fl_getHDC()); +#else + context_->makeCurrent(fl_display, fl_window); +#endif // WIN32 + } + + if (!valid()) { + // Update the viewport for this context... + context_->setViewport(0, 0, w(), h()); + } + + // Clear the window... + context_->clear(csContext::COLOR_CLEAR | csContext::DEPTH_CLEAR, + 0.0f, // Red + 0.0f, // Green + 0.0f, // Blue + 1.0f); // Alpha + + // Then draw the scene (if any)... + if (scene_) + draw_action_->apply(scene_); +} +</PRE></UL> + +<H4>The scene() Method</H4> + +<P>The <TT>scene()</TT> method sets the scene to be drawn. The scene is +a collection of 3D objects in a <TT>csGroup</TT>. The scene is redrawn +after this call. + +*/ |
