1 /********************************************************************************
2 *                                                                               *
3 *                      O p e n G L   V i e w e r   W i d g e t                  *
4 *                                                                               *
5 *********************************************************************************
6 * Copyright (C) 1997,2020 by Jeroen van der Zijp.   All Rights Reserved.        *
7 *********************************************************************************
8 * This library is free software; you can redistribute it and/or modify          *
9 * it under the terms of the GNU Lesser General Public License as published by   *
10 * the Free Software Foundation; either version 3 of the License, or             *
11 * (at your option) any later version.                                           *
12 *                                                                               *
13 * This library is distributed in the hope that it will be useful,               *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of                *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                 *
16 * GNU Lesser General Public License for more details.                           *
17 *                                                                               *
18 * You should have received a copy of the GNU Lesser General Public License      *
19 * along with this program.  If not, see <http://www.gnu.org/licenses/>          *
20 ********************************************************************************/
21 #ifndef FXGLVIEWER_H
22 #define FXGLVIEWER_H
23 
24 #ifndef FXGLCANVAS_H
25 #include "FXGLCanvas.h"
26 #endif
27 
28 namespace FX {
29 
30 
31 class FXDCPrint;
32 class FXGLObject;
33 class FXGLVisual;
34 
35 
36 // GL Viewer options
37 enum {
38   GLVIEWER_LIGHTING = 0x00010000,    /// Lighting is on
39   GLVIEWER_FOG      = 0x00020000,    /// Fog mode on
40   GLVIEWER_DITHER   = 0x00040000     /// Dithering
41   };
42 
43 
44 /*******************************  Viewer  Structs  *****************************/
45 
46 
47 /// OpenGL Viewer Viewport
48 struct FXViewport {
49   FXint      w;                 /// Viewport width
50   FXint      h;                 /// Viewport height
51   FXdouble   left;              /// World left
52   FXdouble   right;             /// World right
53   FXdouble   bottom;            /// World bottom
54   FXdouble   top;               /// World top
55   FXdouble   hither;            /// World hither (near)
56   FXdouble   yon;               /// World yon (far)
57   };
58 
59 
60 /// OpenGL Light Source
61 struct FXAPI FXLight {
62   FXVec4f    ambient;           /// Ambient light color
63   FXVec4f    diffuse;           /// Diffuse light color
64   FXVec4f    specular;          /// Specular light color
65   FXVec4f    position;          /// Light position
66   FXVec3f    direction;         /// Spot direction
67   FXfloat    exponent;          /// Spotlight exponent
68   FXfloat    cutoff;            /// Spotlight cutoff angle
69   FXfloat    c_attn;            /// Constant attenuation factor
70   FXfloat    l_attn;            /// Linear attenuation factor
71   FXfloat    q_attn;            /// Quadratic attenuation factor
72   };
73 
74 
75 /// OpenGL Material Description
76 struct FXAPI FXMaterial {
77   FXVec4f    ambient;           /// Ambient material color
78   FXVec4f    diffuse;           /// Diffuse material color
79   FXVec4f    specular;          /// Specular material color
80   FXVec4f    emission;          /// Emissive material color
81   FXfloat    shininess;         /// Specular shininess
82   };
83 
84 
85 // Feedback buffer sort routine
86 typedef FXbool (*FXZSortFunc)(FXfloat*& buffer,FXint& used,FXint& size);
87 
88 
89 /********************************  Viewer  Class  ******************************/
90 
91 
92 /// OpenGL viewer widget
93 class FXAPI FXGLViewer : public FXGLCanvas {
94   FXDECLARE(FXGLViewer)
95   friend class FXGLObject;
96 protected:
97   FXViewport      wvt;              // Window viewport transform
98   FXMat4f         transform;        // Current transformation matrix
99   FXMat4f         itransform;       // Inverse of current transformation matrix
100   FXuint          projection;       // Projection mode
101   FXQuatf         rotation;         // Viewer orientation
102   FXdouble        fov;              // Field of view
103   FXdouble        zoom;             // Zoom factor
104   FXVec3f         center;           // Model center
105   FXVec3f         scale;            // Model scale
106   FXdouble        worldpx;          // Pixel size in world
107   FXdouble        modelpx;          // Pixel size in model
108   FXint           maxhits;          // Maximum number of hits
109   FXdouble        ax,ay;            // Quick view->world coordinate mapping
110   FXdouble        diameter;         // Size of model diameter ( always > 0)
111   FXdouble        distance;         // Distance of PRP to target
112   FXVec4f         background[2];    // Background colors
113   FXVec4f         ambient;          // Global ambient light
114   FXLight         light;            // Light source
115   FXMaterial      material;         // Base material properties
116   FXint           dial[3];          // Dial positions
117   FXString        help;             // Status help
118   FXString        tip;              // Tooltip for background
119   FXGLObject     *dropped;          // Object being dropped on
120   FXGLObject     *selection;        // Current object
121   FXZSortFunc     zsortfunc;        // Routine to sort feedback buffer
122   FXGLObject     *scene;            // What we're looking at
123   FXbool          doesturbo;        // Doing turbo mode
124   FXbool          turbomode;        // Turbo mode
125   FXuchar         mode;             // Mode the widget is in
126 public:
127 
128   // Common DND types
129   static FXDragType objectType;     // GL Object type
130 
131 protected:
132 
133   // Mouse actions when in viewing window
134   enum {
135     HOVERING,                       // Hovering mouse w/o doing anything
136     PICKING,                        // Pick mode
137     ROTATING,                       // Rotating camera around target
138     POSTING,                        // Posting right-mouse menu
139     TRANSLATING,                    // Translating camera
140     ZOOMING,                        // Zooming
141     FOVING,                         // Change field-of-view
142     DRAGGING,                       // Dragging objects
143     TRUCKING,                       // Trucking camera
144     GYRATING,                       // Rotation of camera around eye
145     DO_LASSOSELECT,                 // Lasso select when mouse pressed
146     LASSOSELECT,                    // Anchor of lasso rectangle
147     DO_LASSOZOOM,                   // Zoom when mouse pressed
148     LASSOZOOM                       // Zoom rectangle
149     };
150 
151 protected:
152   FXGLViewer();
153   void glsetup();
154   virtual void updateProjection();
155   virtual void updateTransform();
156   FXVec3f spherePoint(FXint px,FXint py);
157   FXQuatf turn(FXint fx,FXint fy,FXint tx,FXint ty);
158   void drawWorld(FXViewport& wv);
159   void drawAnti(FXViewport& wv);
160   void drawLasso(FXint x0,FXint y0,FXint x1,FXint y1);
161   FXint selectHits(FXuint*& hits,FXint& nhits,FXint x,FXint y,FXint w,FXint h);
162   FXint renderFeedback(FXfloat *buffer,FXint x,FXint y,FXint w,FXint h,FXint maxbuffer);
163   void drawFeedback(FXDCPrint& pdc,const FXfloat* buffer,FXint used);
164   virtual FXGLObject* processHits(FXuint *pickbuffer,FXint nhits);
165   void setOp(FXuint o);
166 private:
167   FXGLViewer(const FXGLViewer&);
168   FXGLViewer &operator=(const FXGLViewer&);
169   void initialize();
170 public:
171 
172   // Events
173   long onPaint(FXObject*,FXSelector,void*);
174   long onEnter(FXObject*,FXSelector,void*);
175   long onLeave(FXObject*,FXSelector,void*);
176   long onMotion(FXObject*,FXSelector,void*);
177   long onMouseWheel(FXObject*,FXSelector,void*);
178   long onChanged(FXObject*,FXSelector,void*);
179   long onPick(FXObject*,FXSelector,void*);
180   long onClicked(FXObject*,FXSelector,void*);
181   long onDoubleClicked(FXObject*,FXSelector,void*);
182   long onTripleClicked(FXObject*,FXSelector,void*);
183   long onLassoed(FXObject*,FXSelector,void*);
184   long onSelected(FXObject*,FXSelector,void*);
185   long onDeselected(FXObject*,FXSelector,void*);
186   long onInserted(FXObject*,FXSelector,void*);
187   long onDeleted(FXObject*,FXSelector,void*);
188   long onLeftBtnPress(FXObject*,FXSelector,void*);
189   long onLeftBtnRelease(FXObject*,FXSelector,void*);
190   long onMiddleBtnPress(FXObject*,FXSelector,void*);
191   long onMiddleBtnRelease(FXObject*,FXSelector,void*);
192   long onRightBtnPress(FXObject*,FXSelector,void*);
193   long onRightBtnRelease(FXObject*,FXSelector,void*);
194   long onSpaceBallMotion(FXObject*,FXSelector,void*);
195   long onUngrabbed(FXObject*,FXSelector,void*);
196   long onKeyPress(FXObject*,FXSelector,void*);
197   long onKeyRelease(FXObject*,FXSelector,void*);
198   long onFocusIn(FXObject*,FXSelector,void*);
199   long onFocusOut(FXObject*,FXSelector,void*);
200   long onClipboardLost(FXObject*,FXSelector,void*);
201   long onClipboardGained(FXObject*,FXSelector,void*);
202   long onClipboardRequest(FXObject*,FXSelector,void*);
203 
204   // Commands
205   long onCmdPerspective(FXObject*,FXSelector,void*);
206   long onUpdPerspective(FXObject*,FXSelector,void*);
207   long onCmdParallel(FXObject*,FXSelector,void*);
208   long onUpdParallel(FXObject*,FXSelector,void*);
209   long onCmdFront(FXObject*,FXSelector,void*);
210   long onUpdFront(FXObject*,FXSelector,void*);
211   long onCmdBack(FXObject*,FXSelector,void*);
212   long onUpdBack(FXObject*,FXSelector,void*);
213   long onCmdLeft(FXObject*,FXSelector,void*);
214   long onUpdLeft(FXObject*,FXSelector,void*);
215   long onCmdRight(FXObject*,FXSelector,void*);
216   long onUpdRight(FXObject*,FXSelector,void*);
217   long onCmdTop(FXObject*,FXSelector,void*);
218   long onUpdTop(FXObject*,FXSelector,void*);
219   long onCmdBottom(FXObject*,FXSelector,void*);
220   long onUpdBottom(FXObject*,FXSelector,void*);
221   long onCmdResetView(FXObject*,FXSelector,void*);
222   long onCmdFitView(FXObject*,FXSelector,void*);
223   long onDNDEnter(FXObject*,FXSelector,void*);
224   long onDNDLeave(FXObject*,FXSelector,void*);
225   long onDNDMotion(FXObject*,FXSelector,void*);
226   long onDNDDrop(FXObject*,FXSelector,void*);
227   long onTipTimer(FXObject*,FXSelector,void*);
228   long onCmdXYZDial(FXObject*,FXSelector,void*);
229   long onUpdXYZDial(FXObject*,FXSelector,void*);
230   long onCmdRollPitchYaw(FXObject*,FXSelector,void*);
231   long onUpdRollPitchYaw(FXObject*,FXSelector,void*);
232   long onCmdXYZScale(FXObject*,FXSelector,void*);
233   long onUpdXYZScale(FXObject*,FXSelector,void*);
234   long onUpdCurrent(FXObject*,FXSelector,void*);
235   long onCmdCutSel(FXObject*,FXSelector,void*);
236   long onCmdCopySel(FXObject*,FXSelector,void*);
237   long onCmdPasteSel(FXObject*,FXSelector,void*);
238   long onCmdDeleteSel(FXObject*,FXSelector,void*);
239   long onUpdDeleteSel(FXObject*,FXSelector,void*);
240   long onCmdBackColor(FXObject*,FXSelector,void*);
241   long onUpdBackColor(FXObject*,FXSelector,void*);
242   long onCmdGradientBackColor(FXObject*,FXSelector,void*);
243   long onUpdGradientBackColor(FXObject*,FXSelector,void*);
244   long onCmdAmbientColor(FXObject*,FXSelector,void*);
245   long onUpdAmbientColor(FXObject*,FXSelector,void*);
246   long onCmdLighting(FXObject*,FXSelector,void*);
247   long onUpdLighting(FXObject*,FXSelector,void*);
248   long onCmdFog(FXObject*,FXSelector,void*);
249   long onUpdFog(FXObject*,FXSelector,void*);
250   long onCmdDither(FXObject*,FXSelector,void*);
251   long onUpdDither(FXObject*,FXSelector,void*);
252   long onCmdFov(FXObject*,FXSelector,void*);
253   long onUpdFov(FXObject*,FXSelector,void*);
254   long onCmdZoom(FXObject*,FXSelector,void*);
255   long onUpdZoom(FXObject*,FXSelector,void*);
256   long onCmdLightAmbient(FXObject*,FXSelector,void*);
257   long onUpdLightAmbient(FXObject*,FXSelector,void*);
258   long onCmdLightDiffuse(FXObject*,FXSelector,void*);
259   long onUpdLightDiffuse(FXObject*,FXSelector,void*);
260   long onCmdLightSpecular(FXObject*,FXSelector,void*);
261   long onUpdLightSpecular(FXObject*,FXSelector,void*);
262   long onCmdTurbo(FXObject*,FXSelector,void*);
263   long onUpdTurbo(FXObject*,FXSelector,void*);
264   long onCmdPrintImage(FXObject*,FXSelector,void*);
265   long onCmdPrintVector(FXObject*,FXSelector,void*);
266   long onCmdLassoZoom(FXObject*,FXSelector,void*);
267   long onCmdLassoSelect(FXObject*,FXSelector,void*);
268   long onQueryHelp(FXObject*,FXSelector,void*);
269   long onQueryTip(FXObject*,FXSelector,void*);
270   virtual long onDefault(FXObject*,FXSelector,void*);
271 
272 public:
273 
274   // Projection modes
275   enum {
276     PARALLEL,		  // Parallel projection
277     PERSPECTIVE		  // Perspective projection
278     };
279 
280   // Messages
281   enum {
282     ID_PERSPECTIVE=FXGLCanvas::ID_LAST,
283     ID_PARALLEL,
284     ID_FRONT,
285     ID_BACK,
286     ID_LEFT,
287     ID_RIGHT,
288     ID_TOP,
289     ID_BOTTOM,
290     ID_RESETVIEW,
291     ID_FITVIEW,
292     ID_TOP_COLOR,
293     ID_BOTTOM_COLOR,
294     ID_BACK_COLOR,
295     ID_AMBIENT_COLOR,
296     ID_LIGHT_AMBIENT,
297     ID_LIGHT_DIFFUSE,
298     ID_LIGHT_SPECULAR,
299     ID_LIGHTING,
300     ID_TURBO,
301     ID_FOG,
302     ID_DITHER,
303     ID_SCALE_X,
304     ID_SCALE_Y,
305     ID_SCALE_Z,
306     ID_DIAL_X,
307     ID_DIAL_Y,
308     ID_DIAL_Z,
309     ID_ROLL,
310     ID_PITCH,
311     ID_YAW,
312     ID_FOV,
313     ID_ZOOM,
314     ID_CUT_SEL,
315     ID_COPY_SEL,
316     ID_PASTE_SEL,
317     ID_DELETE_SEL,
318     ID_PRINT_IMAGE,
319     ID_PRINT_VECTOR,
320     ID_LASSO_ZOOM,
321     ID_LASSO_SELECT,
322     ID_LAST
323     };
324 
325 public:
326 
327   // Common DND type names
328   static const FXchar objectTypeName[];
329 
330 public:
331 
332   /// Construct GL viewer widget
333   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);
334 
335   /// Construct GL viewer widget sharing display lists with another GL canvas
336   FXGLViewer(FXComposite* p,FXGLVisual *vis,FXGLCanvas* share,FXObject* tgt=NULL,FXSelector sel=0,FXuint opts=0,FXint x=0,FXint y=0,FXint w=0,FXint h=0);
337 
338   /// Construct GL viewer widget sharing context
339   FXGLViewer(FXComposite* p,FXGLContext* ctx,FXObject* tgt=NULL,FXSelector sel=0,FXuint opts=0,FXint x=0,FXint y=0,FXint w=0,FXint h=0);
340 
341   /// Create all of the server-side resources for this window
342   virtual void create();
343 
344   /// Detach server-side resources
345   virtual void detach();
346 
347   /// Perform layout
348   virtual void layout();
349 
350   /// Return size of pixel in world coordinates
worldPix()351   FXdouble worldPix() const { return worldpx; }
352 
353   /// Return size of pixel in model coordinates
modelPix()354   FXdouble modelPix() const { return modelpx; }
355 
356   /// Return a NULL-terminated list of all objects in the given rectangle, or NULL
357   FXGLObject** lasso(FXint x1,FXint y1,FXint x2,FXint y2);
358 
359   /// Return a NULL-terminated list of all objects in the given rectangle, or NULL
360   virtual FXGLObject** select(FXint x,FXint y,FXint w,FXint h);
361 
362   /// Perform a pick operation, returning the object at the given x,y position, or NULL
363   virtual FXGLObject* pick(FXint x,FXint y);
364 
365   /// Change the model bounding box; this adjusts the viewer
366   virtual FXbool setBounds(const FXRangef& box);
367 
368   /// Fit viewer to the given bounding box
369   FXbool fitToBounds(const FXRangef& box);
370 
371   /// Return the viewer's viewport
372   void getViewport(FXViewport& v) const;
373 
374   /// Translate eye-coordinate to screen coordinate
375   void eyeToScreen(FXint& sx,FXint& sy,FXVec3f e);
376 
377   /// Translate screen coordinate to eye coordinate at the given depth
378   FXVec3f screenToEye(FXint sx,FXint sy,FXfloat eyez=0.0f);
379 
380   /// Translate screen coordinate to eye coordinate at the target point depth
381   FXVec3f screenToTarget(FXint sx,FXint sy);
382 
383   /// Translate world coordinate to eye coordinate
384   FXVec3f worldToEye(FXVec3f w);
385 
386   /// Translate world coordinate to eye coordinate depth
387   FXfloat worldToEyeZ(FXVec3f w);
388 
389   /// Translate eye coordinate to eye coordinate
390   FXVec3f eyeToWorld(FXVec3f e);
391 
392   /// Calculate world coordinate vector from screen movement
393   FXVec3f worldVector(FXint fx,FXint fy,FXint tx,FXint ty);
394 
395   ///  Change default object material setting
396   void setMaterial(const FXMaterial &mtl);
397 
398   /// Return default object material setting
399   void getMaterial(FXMaterial &mtl) const;
400 
401   /// Change camera field of view angle (in degrees)
402   void setFieldOfView(FXdouble fv);
403 
404   /// Return camera field of view angle
getFieldOfView()405   FXdouble getFieldOfView() const { return fov; }
406 
407   /// Change camera zoom factor
408   void setZoom(FXdouble zm);
409 
410   /// Return camera zoom factor
getZoom()411   FXdouble getZoom() const { return zoom; }
412 
413   /// Change target point distance
414   void setDistance(FXdouble ed);
415 
416   /// Return target point distance
getDistance()417   FXdouble getDistance() const { return distance; }
418 
419   /// Change unequal model scaling factors
420   void setScale(FXVec3f s);
421 
422   /// Return current scaling factors
getScale()423   const FXVec3f& getScale() const { return scale; }
424 
425   /// Change camera orientation from quaternion
426   void setOrientation(FXQuatf rot);
427 
428   /// Return current camera orientation quaternion
getOrientation()429   const FXQuatf& getOrientation() const { return rotation; }
430 
431   /// Change object center (tranlation)
432   void setCenter(FXVec3f cntr);
433 
434   /// Return object center
getCenter()435   const FXVec3f& getCenter() const { return center; }
436 
437   /// Translate object center
438   void translate(FXVec3f vec);
439 
440   /// Return boresight vector
441   FXbool getBoreVector(FXint sx,FXint sy,FXVec3f& point,FXVec3f& dir);
442 
443   /// Return eyesight vector
444   FXVec3f getEyeVector() const;
445 
446   /// Return eye position
447   FXVec3f getEyePosition() const;
448 
449   /// Change help text
450   void setHelpText(const FXString& text);
451 
452   /// Return help text
getHelpText()453   const FXString& getHelpText() const { return help; }
454 
455   /// Change tip text
456   void setTipText(const FXString&  text);
457 
458   /// Return tip text
getTipText()459   const FXString& getTipText() const { return tip; }
460 
461   /// Return the current transformation matrix
getTransform()462   const FXMat4f& getTransform() const { return transform; }
463 
464   /// Return the inverse of the current transformation matrix
getInvTransform()465   const FXMat4f& getInvTransform() const { return itransform; }
466 
467   /// Change the scene, i.e. the object being displayed.
468   void setScene(FXGLObject* sc);
469 
470   /// Return the current scene object
getScene()471   FXGLObject* getScene() const { return scene; }
472 
473   /// Change selection
474   void setSelection(FXGLObject* sel);
475 
476   /// Return selection
getSelection()477   FXGLObject* getSelection() const { return selection; }
478 
479   /// Change the projection mode, PERSPECTIVE or PARALLEL
480   void setProjection(FXuint proj);
481 
482   /// Return the projection mode
getProjection()483   FXuint getProjection() const { return projection; }
484 
485   /// Change both top and bottom background colors
486   void setBackgroundColor(const FXVec4f& clr);
487 
488   /// Change top or bottom background color
489   void setBackgroundColor(const FXVec4f& clr,FXbool bottom);
490 
491   /// Return top or bottom window background color
getBackgroundColor(FXbool bottom)492   const FXVec4f& getBackgroundColor(FXbool bottom) const { return background[bottom]; }
493 
494   /// Change global ambient light color
495   void setAmbientColor(const FXVec4f& clr);
496 
497   /// Return global ambient light color
getAmbientColor()498   const FXVec4f& getAmbientColor() const { return ambient; }
499 
500   /**
501   * Read the pixels off the screen as array of FXColor;
502   * this array can be directly passed to fxsaveBMP and other image
503   * output routines.
504   */
505   FXbool readPixels(FXColor*& buffer,FXint x,FXint y,FXint w,FXint h);
506 
507   /**
508   * Read the feedback buffer containing the current scene, returning used
509   * and allocated size.
510   */
511   FXbool readFeedback(FXfloat*& buffer,FXint& used,FXint& size,FXint x,FXint y,FXint w,FXint h);
512 
513   /**
514   * Change hidden-surface feedback buffer sorting algorithm.
515   * This can be used for move/draw printed output depth sorting.
516   */
setZSortFunc(FXZSortFunc func)517   void setZSortFunc(FXZSortFunc func){ zsortfunc=func; }
518 
519   /// Return hidden surface sorting function.
getZSortFunc()520   FXZSortFunc getZSortFunc() const { return zsortfunc; }
521 
522   /**
523   * Change the maximum hits, i.e. the maximum size of the pick buffer.
524   * When set to less than or equal to zero, picking is essentially turned off.
525   */
setMaxHits(FXint maxh)526   void setMaxHits(FXint maxh) { maxhits=maxh; }
527 
528   /// Return maximum pickbuffer size
getMaxHits()529   FXint getMaxHits() const { return maxhits; }
530 
531   /**
532   * When drawing a GL object, if doesTurbo() is true, the object
533   * may choose to perform a reduced complexity drawing as the user is
534   * interactively manipulating; another update will be done later when
535   * the full complexity drawing can be performed again.
536   */
doesTurbo()537   FXbool doesTurbo() const { return doesturbo; }
538 
539   /// Return turbo mode setting
getTurboMode()540   FXbool getTurboMode() const { return turbomode; }
541 
542   /// Set turbo mode
543   void setTurboMode(FXbool turbo=true);
544 
545   /// Return light source settings
546   void getLight(FXLight& lite) const;
547 
548   /// Change light source settings
549   void setLight(const FXLight& lite);
550 
551   /// Save viewer to a stream
552   virtual void save(FXStream& store) const;
553 
554   /// Load viewer from a stream
555   virtual void load(FXStream& store);
556 
557   /// Destructor
558   virtual ~FXGLViewer();
559   };
560 
561 }
562 
563 #endif
564 
565