Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members

FXGLViewer.h

Go to the documentation of this file.
00001 /********************************************************************************
00002 *                                                                               *
00003 *                      O p e n G L   V i e w e r   W i d g e t                  *
00004 *                                                                               *
00005 *********************************************************************************
00006 * Copyright (C) 1997,2006 by Jeroen van der Zijp.   All Rights Reserved.        *
00007 *********************************************************************************
00008 * This library is free software; you can redistribute it and/or                 *
00009 * modify it under the terms of the GNU Lesser General Public                    *
00010 * License as published by the Free Software Foundation; either                  *
00011 * version 2.1 of the License, or (at your option) any later version.            *
00012 *                                                                               *
00013 * This library is distributed in the hope that it will be useful,               *
00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of                *
00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU             *
00016 * Lesser General Public License for more details.                               *
00017 *                                                                               *
00018 * You should have received a copy of the GNU Lesser General Public              *
00019 * License along with this library; if not, write to the Free Software           *
00020 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.    *
00021 *********************************************************************************
00022 * $Id: FXGLViewer.h,v 1.74 2006/01/22 17:58:04 fox Exp $                        *
00023 ********************************************************************************/
00024 #ifndef FXGLVIEWER_H
00025 #define FXGLVIEWER_H
00026 
00027 #ifndef FXGLCANVAS_H
00028 #include "FXGLCanvas.h"
00029 #endif
00030 
00031 namespace FX {
00032 
00033 
00034 class FXDCPrint;
00035 class FXGLObject;
00036 class FXGLVisual;
00037 
00038 
00039 // GL Viewer options
00040 enum {
00041   VIEWER_LIGHTING = 0x00008000,    /// Lighting is on
00042   VIEWER_FOG      = 0x00010000,    /// Fog mode on
00043   VIEWER_DITHER   = 0x00020000     /// Dithering
00044   };
00045 
00046 
00047 /*******************************  Viewer  Structs  *****************************/
00048 
00049 
00050 /// OpenGL Viewer Viewport
00051 struct FXViewport {
00052   FXint      w,h;               // Viewport dimensions
00053   FXdouble   left,right;        // World box
00054   FXdouble   bottom,top;
00055   FXdouble   hither,yon;
00056   };
00057 
00058 
00059 // OpenGL Light Source
00060 struct FXAPI FXLight {
00061   FXVec4f    ambient;           // Ambient light color
00062   FXVec4f    diffuse;           // Diffuse light color
00063   FXVec4f    specular;          // Specular light color
00064   FXVec4f    position;          // Light position
00065   FXVec3f    direction;         // Spot direction
00066   FXfloat    exponent;          // Spotlight exponent
00067   FXfloat    cutoff;            // Spotlight cutoff angle
00068   FXfloat    c_attn;            // Constant attenuation factor
00069   FXfloat    l_attn;            // Linear attenuation factor
00070   FXfloat    q_attn;            // Quadratic attenuation factor
00071   };
00072 
00073 
00074 // OpenGL Material Description
00075 struct FXAPI FXMaterial {
00076   FXVec4f    ambient;           // Ambient material color
00077   FXVec4f    diffuse;           // Diffuse material color
00078   FXVec4f    specular;          // Specular material color
00079   FXVec4f    emission;          // Emissive material color
00080   FXfloat    shininess;         // Specular shininess
00081   };
00082 
00083 
00084 // Feedback buffer sort routine
00085 typedef FXbool (*FXZSortFunc)(FXfloat*& buffer,FXint& used,FXint& size);
00086 
00087 
00088 /********************************  Viewer  Class  ******************************/
00089 
00090 
00091 /// OpenGL viewer widget
00092 class FXAPI FXGLViewer : public FXGLCanvas {
00093   FXDECLARE(FXGLViewer)
00094   friend class FXGLObject;
00095 protected:
00096   FXViewport      wvt;              // Window viewport transform
00097   FXMat4f         transform;        // Current transformation matrix
00098   FXMat4f         itransform;       // Inverse of current transformation matrix
00099   FXuint          projection;       // Projection mode
00100   FXQuatf         rotation;         // Viewer orientation
00101   FXdouble        fov;              // Field of view
00102   FXdouble        zoom;             // Zoom factor
00103   FXVec3f         center;           // Model center
00104   FXVec3f         scale;            // Model scale
00105   FXdouble        worldpx;          // Pixel size in world
00106   FXdouble        modelpx;          // Pixel size in model
00107   FXint           maxhits;          // Maximum number of hits
00108   FXdouble        ax,ay;            // Quick view->world coordinate mapping
00109   FXdouble        diameter;         // Size of model diameter ( always > 0)
00110   FXdouble        distance;         // Distance of PRP to target
00111   FXVec4f         background[2];    // Background colors
00112   FXVec4f         ambient;          // Global ambient light
00113   FXLight         light;            // Light source
00114   FXMaterial      material;         // Base material properties
00115   FXint           dial[3];          // Dial positions
00116   FXString        help;             // Status help
00117   FXString        tip;              // Tooltip for background
00118   FXGLObject     *dropped;          // Object being dropped on
00119   FXGLObject     *selection;        // Current object
00120   FXZSortFunc     zsortfunc;        // Routine to sort feedback buffer
00121   FXGLObject     *scene;            // What we're looking at
00122   FXbool          doesturbo;        // Doing turbo mode
00123   FXbool          turbomode;        // Turbo mode
00124   FXuchar         mode;             // Mode the widget is in
00125 public:
00126 
00127   // Common DND types
00128   static FXDragType objectType;     // GL Object type
00129 
00130 protected:
00131 
00132   // Mouse actions when in viewing window
00133   enum {
00134     HOVERING,                       // Hovering mouse w/o doing anything
00135     PICKING,                        // Pick mode
00136     ROTATING,                       // Rotating camera around target
00137     POSTING,                        // Posting right-mouse menu
00138     TRANSLATING,                    // Translating camera
00139     ZOOMING,                        // Zooming
00140     FOVING,                         // Change field-of-view
00141     DRAGGING,                       // Dragging objects
00142     TRUCKING,                       // Trucking camera
00143     GYRATING,                       // Rotation of camera around eye
00144     DO_LASSOSELECT,                 // Lasso select when mouse pressed
00145     LASSOSELECT,                    // Anchor of lasso rectangle
00146     DO_LASSOZOOM,                   // Zoom when mouse pressed
00147     LASSOZOOM                       // Zoom rectangle
00148     };
00149 
00150 protected:
00151   FXGLViewer();
00152   void glsetup();
00153   virtual void updateProjection();
00154   virtual void updateTransform();
00155   FXVec3f spherePoint(FXint px,FXint py);
00156   FXQuatf turn(FXint fx,FXint fy,FXint tx,FXint ty);
00157   void drawWorld(FXViewport& wv);
00158   void drawAnti(FXViewport& wv);
00159   void drawLasso(FXint x0,FXint y0,FXint x1,FXint y1);
00160   FXint selectHits(FXuint*& hits,FXint& nhits,FXint x,FXint y,FXint w,FXint h);
00161   FXint renderFeedback(FXfloat *buffer,FXint x,FXint y,FXint w,FXint h,FXint maxbuffer);
00162   void drawFeedback(FXDCPrint& pdc,const FXfloat* buffer,FXint used);
00163   virtual FXGLObject* processHits(FXuint *pickbuffer,FXint nhits);
00164   void setOp(FXuint o);
00165 private:
00166   FXGLViewer(const FXGLViewer&);
00167   FXGLViewer &operator=(const FXGLViewer&);
00168   void initialize();
00169 public:
00170 
00171   // Events
00172   long onPaint(FXObject*,FXSelector,void*);
00173   long onEnter(FXObject*,FXSelector,void*);
00174   long onLeave(FXObject*,FXSelector,void*);
00175   long onMotion(FXObject*,FXSelector,void*);
00176   long onMouseWheel(FXObject*,FXSelector,void*);
00177   long onChanged(FXObject*,FXSelector,void*);
00178   long onPick(FXObject*,FXSelector,void*);
00179   long onClicked(FXObject*,FXSelector,void*);
00180   long onDoubleClicked(FXObject*,FXSelector,void*);
00181   long onTripleClicked(FXObject*,FXSelector,void*);
00182   long onLassoed(FXObject*,FXSelector,void*);
00183   long onSelected(FXObject*,FXSelector,void*);
00184   long onDeselected(FXObject*,FXSelector,void*);
00185   long onInserted(FXObject*,FXSelector,void*);
00186   long onDeleted(FXObject*,FXSelector,void*);
00187   long onLeftBtnPress(FXObject*,FXSelector,void*);
00188   long onLeftBtnRelease(FXObject*,FXSelector,void*);
00189   long onMiddleBtnPress(FXObject*,FXSelector,void*);
00190   long onMiddleBtnRelease(FXObject*,FXSelector,void*);
00191   long onRightBtnPress(FXObject*,FXSelector,void*);
00192   long onRightBtnRelease(FXObject*,FXSelector,void*);
00193   long onUngrabbed(FXObject*,FXSelector,void*);
00194   long onKeyPress(FXObject*,FXSelector,void*);
00195   long onKeyRelease(FXObject*,FXSelector,void*);
00196   long onFocusIn(FXObject*,FXSelector,void*);
00197   long onFocusOut(FXObject*,FXSelector,void*);
00198   long onClipboardLost(FXObject*,FXSelector,void*);
00199   long onClipboardGained(FXObject*,FXSelector,void*);
00200   long onClipboardRequest(FXObject*,FXSelector,void*);
00201 
00202   // Commands
00203   long onCmdPerspective(FXObject*,FXSelector,void*);
00204   long onUpdPerspective(FXObject*,FXSelector,void*);
00205   long onCmdParallel(FXObject*,FXSelector,void*);
00206   long onUpdParallel(FXObject*,FXSelector,void*);
00207   long onCmdFront(FXObject*,FXSelector,void*);
00208   long onUpdFront(FXObject*,FXSelector,void*);
00209   long onCmdBack(FXObject*,FXSelector,void*);
00210   long onUpdBack(FXObject*,FXSelector,void*);
00211   long onCmdLeft(FXObject*,FXSelector,void*);
00212   long onUpdLeft(FXObject*,FXSelector,void*);
00213   long onCmdRight(FXObject*,FXSelector,void*);
00214   long onUpdRight(FXObject*,FXSelector,void*);
00215   long onCmdTop(FXObject*,FXSelector,void*);
00216   long onUpdTop(FXObject*,FXSelector,void*);
00217   long onCmdBottom(FXObject*,FXSelector,void*);
00218   long onUpdBottom(FXObject*,FXSelector,void*);
00219   long onCmdResetView(FXObject*,FXSelector,void*);
00220   long onCmdFitView(FXObject*,FXSelector,void*);
00221   long onDNDEnter(FXObject*,FXSelector,void*);
00222   long onDNDLeave(FXObject*,FXSelector,void*);
00223   long onDNDMotion(FXObject*,FXSelector,void*);
00224   long onDNDDrop(FXObject*,FXSelector,void*);
00225   long onTipTimer(FXObject*,FXSelector,void*);
00226   long onCmdXYZDial(FXObject*,FXSelector,void*);
00227   long onUpdXYZDial(FXObject*,FXSelector,void*);
00228   long onCmdRollPitchYaw(FXObject*,FXSelector,void*);
00229   long onUpdRollPitchYaw(FXObject*,FXSelector,void*);
00230   long onCmdXYZScale(FXObject*,FXSelector,void*);
00231   long onUpdXYZScale(FXObject*,FXSelector,void*);
00232   long onUpdCurrent(FXObject*,FXSelector,void*);
00233   long onCmdCutSel(FXObject*,FXSelector,void*);
00234   long onCmdCopySel(FXObject*,FXSelector,void*);
00235   long onCmdPasteSel(FXObject*,FXSelector,void*);
00236   long onCmdDeleteSel(FXObject*,FXSelector,void*);
00237   long onUpdDeleteSel(FXObject*,FXSelector,void*);
00238   long onCmdBackColor(FXObject*,FXSelector,void*);
00239   long onUpdBackColor(FXObject*,FXSelector,void*);
00240   long onCmdGradientBackColor(FXObject*,FXSelector,void*);
00241   long onUpdGradientBackColor(FXObject*,FXSelector,void*);
00242   long onCmdAmbientColor(FXObject*,FXSelector,void*);
00243   long onUpdAmbientColor(FXObject*,FXSelector,void*);
00244   long onCmdLighting(FXObject*,FXSelector,void*);
00245   long onUpdLighting(FXObject*,FXSelector,void*);
00246   long onCmdFog(FXObject*,FXSelector,void*);
00247   long onUpdFog(FXObject*,FXSelector,void*);
00248   long onCmdDither(FXObject*,FXSelector,void*);
00249   long onUpdDither(FXObject*,FXSelector,void*);
00250   long onCmdFov(FXObject*,FXSelector,void*);
00251   long onUpdFov(FXObject*,FXSelector,void*);
00252   long onCmdZoom(FXObject*,FXSelector,void*);
00253   long onUpdZoom(FXObject*,FXSelector,void*);
00254   long onCmdLightAmbient(FXObject*,FXSelector,void*);
00255   long onUpdLightAmbient(FXObject*,FXSelector,void*);
00256   long onCmdLightDiffuse(FXObject*,FXSelector,void*);
00257   long onUpdLightDiffuse(FXObject*,FXSelector,void*);
00258   long onCmdLightSpecular(FXObject*,FXSelector,void*);
00259   long onUpdLightSpecular(FXObject*,FXSelector,void*);
00260   long onCmdTurbo(FXObject*,FXSelector,void*);
00261   long onUpdTurbo(FXObject*,FXSelector,void*);
00262   long onCmdPrintImage(FXObject*,FXSelector,void*);
00263   long onCmdPrintVector(FXObject*,FXSelector,void*);
00264   long onCmdLassoZoom(FXObject*,FXSelector,void*);
00265   long onCmdLassoSelect(FXObject*,FXSelector,void*);
00266   long onQueryHelp(FXObject*,FXSelector,void*);
00267   long onQueryTip(FXObject*,FXSelector,void*);
00268   virtual long onDefault(FXObject*,FXSelector,void*);
00269 
00270 public:
00271 
00272   // Projection modes
00273   enum {
00274     PARALLEL,     // Parallel projection
00275     PERSPECTIVE     // Perspective projection
00276     };
00277 
00278   // Messages
00279   enum {
00280     ID_PERSPECTIVE=FXGLCanvas::ID_LAST,
00281     ID_PARALLEL,
00282     ID_FRONT,
00283     ID_BACK,
00284     ID_LEFT,
00285     ID_RIGHT,
00286     ID_TOP,
00287     ID_BOTTOM,
00288     ID_RESETVIEW,
00289     ID_FITVIEW,
00290     ID_TOP_COLOR,
00291     ID_BOTTOM_COLOR,
00292     ID_BACK_COLOR,
00293     ID_AMBIENT_COLOR,
00294     ID_LIGHT_AMBIENT,
00295     ID_LIGHT_DIFFUSE,
00296     ID_LIGHT_SPECULAR,
00297     ID_LIGHTING,
00298     ID_TURBO,
00299     ID_FOG,
00300     ID_DITHER,
00301     ID_SCALE_X,
00302     ID_SCALE_Y,
00303     ID_SCALE_Z,
00304     ID_DIAL_X,
00305     ID_DIAL_Y,
00306     ID_DIAL_Z,
00307     ID_ROLL,
00308     ID_PITCH,
00309     ID_YAW,
00310     ID_FOV,
00311     ID_ZOOM,
00312     ID_CUT_SEL,
00313     ID_COPY_SEL,
00314     ID_PASTE_SEL,
00315     ID_DELETE_SEL,
00316     ID_PRINT_IMAGE,
00317     ID_PRINT_VECTOR,
00318     ID_LASSO_ZOOM,
00319     ID_LASSO_SELECT,
00320     ID_LAST
00321     };
00322 
00323 public:
00324 
00325   // Common DND type names
00326   static const FXchar objectTypeName[];
00327 
00328 public:
00329 
00330   /// Construct GL viewer widget
00331   FXGLViewer(FXComposite* p,FXGLVisual *vis,FXObject* tgt=NULL,FXSelector sel=0,FXuint opts=0,FXint x=0,FXint y=0,FXint w=0,FXint h=0);
00332 
00333   /// Construct GL viewer widget sharing display list with another GL viewer
00334   FXGLViewer(FXComposite* p,FXGLVisual *vis,FXGLViewer* sharegroup,FXObject* tgt=NULL,FXSelector sel=0,FXuint opts=0,FXint x=0,FXint y=0,FXint w=0,FXint h=0);
00335 
00336   /// Create all of the server-side resources for this window
00337   virtual void create();
00338 
00339   /// Detach server-side resources
00340   virtual void detach();
00341 
00342   /// Perform layout
00343   virtual void layout();
00344 
00345   /// Return size of pixel in world coordinates
00346   FXdouble worldPix() const { return worldpx; }
00347 
00348   /// Return size of pixel in model coordinates
00349   FXdouble modelPix() const { return modelpx; }
00350 
00351   /// Return a NULL-terminated list of all objects in the given rectangle, or NULL
00352   FXGLObject** lasso(FXint x1,FXint y1,FXint x2,FXint y2);
00353 
00354   /// Return a NULL-terminated list of all objects in the given rectangle, or NULL
00355   virtual FXGLObject** select(FXint x,FXint y,FXint w,FXint h);
00356 
00357   /// Perform a pick operation, returning the object at the given x,y position, or NULL
00358   virtual FXGLObject* pick(FXint x,FXint y);
00359 
00360   /// Change the model bounding box; this adjusts the viewer
00361   virtual FXbool setBounds(const FXRangef& box);
00362 
00363   /// Fit viewer to the given bounding box
00364   FXbool fitToBounds(const FXRangef& box);
00365 
00366   /// Return the viewer's viewport
00367   void getViewport(FXViewport& v) const;
00368 
00369   /// Translate eye-coordinate to screen coordinate
00370   void eyeToScreen(FXint& sx,FXint& sy,FXVec3f e);
00371 
00372   /// Translate screen coordinate to eye coordinate at the given depth
00373   FXVec3f screenToEye(FXint sx,FXint sy,FXfloat eyez=0.0);
00374 
00375   /// Translate screen coordinate to eye coordinate at the target point depth
00376   FXVec3f screenToTarget(FXint sx,FXint sy);
00377 
00378   /// Translate world coordinate to eye coordinate
00379   FXVec3f worldToEye(FXVec3f w);
00380 
00381   /// Translate world coordinate to eye coordinate depth
00382   FXfloat worldToEyeZ(FXVec3f w);
00383 
00384   /// Translate eye coordinate to eye coordinate
00385   FXVec3f eyeToWorld(FXVec3f e);
00386 
00387   /// Calculate world coordinate vector from screen movement
00388   FXVec3f worldVector(FXint fx,FXint fy,FXint tx,FXint ty);
00389 
00390   ///  Change default object material setting
00391   void setMaterial(const FXMaterial &mtl);
00392 
00393   /// Return default object material setting
00394   void getMaterial(FXMaterial &mtl) const;
00395 
00396   /// Change camera field of view angle (in degrees)
00397   void setFieldOfView(FXdouble fv);
00398 
00399   /// Return camera field of view angle
00400   FXdouble getFieldOfView() const { return fov; }
00401 
00402   /// Change camera zoom factor
00403   void setZoom(FXdouble zm);
00404 
00405   /// Return camera zoom factor
00406   FXdouble getZoom() const { return zoom; }
00407 
00408   /// Change target point distance
00409   void setDistance(FXdouble ed);
00410 
00411   /// Return target point distance
00412   FXdouble getDistance() const { return distance; }
00413 
00414   /// Change unequal model scaling factors
00415   void setScale(FXVec3f s);
00416 
00417   /// Return current scaling factors
00418   const FXVec3f& getScale() const { return scale; }
00419 
00420   /// Change camera orientation from quaternion
00421   void setOrientation(FXQuatf rot);
00422 
00423   /// Return current camera orientation quaternion
00424   const FXQuatf& getOrientation() const { return rotation; }
00425 
00426   /// Change object center (tranlation)
00427   void setCenter(FXVec3f cntr);
00428 
00429   /// Return object center
00430   const FXVec3f& getCenter() const { return center; }
00431 
00432   /// Translate object center
00433   void translate(FXVec3f vec);
00434 
00435   /// Return boresight vector
00436   FXbool getBoreVector(FXint sx,FXint sy,FXVec3f& point,FXVec3f& dir);
00437 
00438   /// Return eyesight vector
00439   FXVec3f getEyeVector() const;
00440 
00441   /// Return eye position
00442   FXVec3f getEyePosition() const;
00443 
00444   /// Change help text
00445   void setHelpText(const FXString& text);
00446 
00447   /// Return help text
00448   const FXString& getHelpText() const { return help; }
00449 
00450   /// Change tip text
00451   void setTipText(const FXString&  text);
00452 
00453   /// Return tip text
00454   const FXString& getTipText() const { return tip; }
00455 
00456   /// Return the current transformation matrix
00457   const FXMat4f& getTransform() const { return transform; }
00458 
00459   /// Return the inverse of the current transformation matrix
00460   const FXMat4f& getInvTransform() const { return itransform; }
00461 
00462   /// Change the scene, i.e. the object being displayed.
00463   void setScene(FXGLObject* sc);
00464 
00465   /// Return the current scene object
00466   FXGLObject* getScene() const { return scene; }
00467 
00468   /// Change selection
00469   void setSelection(FXGLObject* sel);
00470 
00471   /// Return selection
00472   FXGLObject* getSelection() const { return selection; }
00473 
00474   /// Change the projection mode, PERSPECTIVE or PARALLEL
00475   void setProjection(FXuint proj);
00476 
00477   /// Return the projection mode
00478   FXuint getProjection() const { return projection; }
00479 
00480   /// Change top or bottom or both background colors
00481   void setBackgroundColor(const FXVec4f& clr,FXbool bottom=MAYBE);
00482 
00483   /// Return top or bottom window background color.
00484   const FXVec4f& getBackgroundColor(FXbool bottom=FALSE) const { return background[bottom]; }
00485 
00486   /// Change global ambient light color
00487   void setAmbientColor(const FXVec4f& clr);
00488 
00489   /// Return global ambient light color
00490   const FXVec4f& getAmbientColor() const { return ambient; }
00491 
00492   /**
00493   * Read the pixels off the screen as array of FXColor;
00494   * this array can be directly passed to fxsaveBMP and other image
00495   * output routines.
00496   */
00497   FXbool readPixels(FXColor*& buffer,FXint x,FXint y,FXint w,FXint h);
00498 
00499   /**
00500   * Read the feedback buffer containing the current scene, returning used
00501   * and allocated size.
00502   */
00503   FXbool readFeedback(FXfloat*& buffer,FXint& used,FXint& size,FXint x,FXint y,FXint w,FXint h);
00504 
00505   /**
00506   * Change hidden-surface feedback buffer sorting algorithm.
00507   * This can be used for move/draw printed output depth sorting.
00508   */
00509   void setZSortFunc(FXZSortFunc func){ zsortfunc=func; }
00510 
00511   /// Return hidden surface sorting function.
00512   FXZSortFunc getZSortFunc() const { return zsortfunc; }
00513 
00514   /**
00515   * Change the maximum hits, i.e. the maximum size of the pick buffer.
00516   * When set to less than or equal to zero, picking is essentially turned off.
00517   */
00518   void setMaxHits(FXint maxh) { maxhits=maxh; }
00519 
00520   /// Return maximum pickbuffer size
00521   FXint getMaxHits() const { return maxhits; }
00522 
00523   /**
00524   * When drawing a GL object, if doesTurbo() is true, the object
00525   * may choose to perform a reduced complexity drawing as the user is
00526   * interactively manipulating; another update will be done later when
00527   * the full complexity drawing can be performed again.
00528   */
00529   FXbool doesTurbo() const { return doesturbo; }
00530 
00531   /// Return turbo mode setting
00532   FXbool getTurboMode() const { return turbomode; }
00533 
00534   /// Set turbo mode
00535   void setTurboMode(FXbool turbo=TRUE);
00536 
00537   /// Return light source settings
00538   void getLight(FXLight& lite) const;
00539 
00540   /// Change light source settings
00541   void setLight(const FXLight& lite);
00542 
00543   /// Save viewer to a stream
00544   virtual void save(FXStream& store) const;
00545 
00546   /// Load viewer from a stream
00547   virtual void load(FXStream& store);
00548 
00549   /// Destructor
00550   virtual ~FXGLViewer();
00551   };
00552 
00553 }
00554 
00555 #endif
00556 

Copyright © 1997-2005 Jeroen van der Zijp