/******************************************************************************** * * * O p e n G L V i e w e r W i d g e t * * * ********************************************************************************* * Copyright (C) 1997,2024 by Jeroen van der Zijp. All Rights Reserved. * ********************************************************************************* * This library is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as published by * * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public License * * along with this program. If not, see * ********************************************************************************/ #ifndef FXGLVIEWER_H #define FXGLVIEWER_H #ifndef FXGLCANVAS_H #include "FXGLCanvas.h" #endif namespace FX { class FXDCPrint; class FXGLObject; class FXGLVisual; // GL Viewer options enum { GLVIEWER_LIGHTING = 0x00010000, /// Lighting is on GLVIEWER_FOG = 0x00020000, /// Fog mode on GLVIEWER_DITHER = 0x00040000 /// Dithering }; /******************************* Viewer Structs *****************************/ /// OpenGL Viewer Viewport struct FXViewport { FXint w; /// Viewport width FXint h; /// Viewport height FXdouble left; /// World left FXdouble right; /// World right FXdouble bottom; /// World bottom FXdouble top; /// World top FXdouble hither; /// World hither (near) FXdouble yon; /// World yon (far) }; /// OpenGL Light Source struct FXAPI FXLight { FXVec4f ambient; /// Ambient light color FXVec4f diffuse; /// Diffuse light color FXVec4f specular; /// Specular light color FXVec4f position; /// Light position FXVec3f direction; /// Spot direction FXfloat exponent; /// Spotlight exponent FXfloat cutoff; /// Spotlight cutoff angle FXfloat c_attn; /// Constant attenuation factor FXfloat l_attn; /// Linear attenuation factor FXfloat q_attn; /// Quadratic attenuation factor }; /// OpenGL Material Description struct FXAPI FXMaterial { FXVec4f ambient; /// Ambient material color FXVec4f diffuse; /// Diffuse material color FXVec4f specular; /// Specular material color FXVec4f emission; /// Emissive material color FXfloat shininess; /// Specular shininess }; // Feedback buffer sort routine typedef FXbool (*FXZSortFunc)(FXfloat*& buffer,FXint& used,FXint& size); /******************************** Viewer Class ******************************/ /// OpenGL viewer widget class FXAPI FXGLViewer : public FXGLCanvas { FXDECLARE(FXGLViewer) friend class FXGLObject; protected: FXViewport wvt; // Window viewport transform FXMat4f transform; // Current transformation matrix FXMat4f itransform; // Inverse of current transformation matrix FXuint projection; // Projection mode FXQuatf rotation; // Viewer orientation FXdouble fov; // Field of view FXdouble zoom; // Zoom factor FXVec3f center; // Model center FXVec3f scale; // Model scale FXdouble worldpx; // Pixel size in world FXdouble modelpx; // Pixel size in model FXint maxhits; // Maximum number of hits FXdouble ax,ay; // Quick view->world coordinate mapping FXdouble diameter; // Size of model diameter ( always > 0) FXdouble distance; // Distance of PRP to target FXVec4f background[2]; // Background colors FXVec4f ambient; // Global ambient light FXLight light; // Light source FXMaterial material; // Base material properties FXint dial[3]; // Dial positions FXString help; // Status help FXString tip; // Tooltip for background FXGLObject *dropped; // Object being dropped on FXGLObject *selection; // Current object FXZSortFunc zsortfunc; // Routine to sort feedback buffer FXGLObject *scene; // What we're looking at FXbool doesturbo; // Doing turbo mode FXbool turbomode; // Turbo mode FXuchar mode; // Mode the widget is in public: // Common DND types static FXDragType objectType; // GL Object type protected: // Mouse actions when in viewing window enum { HOVERING, // Hovering mouse w/o doing anything PICKING, // Pick mode ROTATING, // Rotating camera around target POSTING, // Posting right-mouse menu TRANSLATING, // Translating camera ZOOMING, // Zooming FOVING, // Change field-of-view DRAGGING, // Dragging objects TRUCKING, // Trucking camera GYRATING, // Rotation of camera around eye DO_LASSOSELECT, // Lasso select when mouse pressed LASSOSELECT, // Anchor of lasso rectangle DO_LASSOZOOM, // Zoom when mouse pressed LASSOZOOM // Zoom rectangle }; protected: FXGLViewer(); void glsetup(); virtual void updateProjection(); virtual void updateTransform(); FXVec3f spherePoint(FXint px,FXint py); FXQuatf turn(FXint fx,FXint fy,FXint tx,FXint ty); void drawWorld(FXViewport& wv); void drawAnti(FXViewport& wv); void drawLasso(FXint x0,FXint y0,FXint x1,FXint y1); FXint selectHits(FXuint*& hits,FXint& nhits,FXint x,FXint y,FXint w,FXint h); FXint renderFeedback(FXfloat *buffer,FXint x,FXint y,FXint w,FXint h,FXint maxbuffer); void drawFeedback(FXDCPrint& pdc,const FXfloat* buffer,FXint used); virtual FXGLObject* processHits(FXuint *pickbuffer,FXint nhits); void setOp(FXuint o); private: FXGLViewer(const FXGLViewer&); FXGLViewer &operator=(const FXGLViewer&); void initialize(); public: // Events long onPaint(FXObject*,FXSelector,void*); long onEnter(FXObject*,FXSelector,void*); long onLeave(FXObject*,FXSelector,void*); long onMotion(FXObject*,FXSelector,void*); long onMouseWheel(FXObject*,FXSelector,void*); long onChanged(FXObject*,FXSelector,void*); long onPick(FXObject*,FXSelector,void*); long onClicked(FXObject*,FXSelector,void*); long onDoubleClicked(FXObject*,FXSelector,void*); long onTripleClicked(FXObject*,FXSelector,void*); long onLassoed(FXObject*,FXSelector,void*); long onSelected(FXObject*,FXSelector,void*); long onDeselected(FXObject*,FXSelector,void*); long onInserted(FXObject*,FXSelector,void*); long onDeleted(FXObject*,FXSelector,void*); long onLeftBtnPress(FXObject*,FXSelector,void*); long onLeftBtnRelease(FXObject*,FXSelector,void*); long onMiddleBtnPress(FXObject*,FXSelector,void*); long onMiddleBtnRelease(FXObject*,FXSelector,void*); long onRightBtnPress(FXObject*,FXSelector,void*); long onRightBtnRelease(FXObject*,FXSelector,void*); long onSpaceBallMotion(FXObject*,FXSelector,void*); long onUngrabbed(FXObject*,FXSelector,void*); long onKeyPress(FXObject*,FXSelector,void*); long onKeyRelease(FXObject*,FXSelector,void*); long onFocusIn(FXObject*,FXSelector,void*); long onFocusOut(FXObject*,FXSelector,void*); long onClipboardLost(FXObject*,FXSelector,void*); long onClipboardGained(FXObject*,FXSelector,void*); long onClipboardRequest(FXObject*,FXSelector,void*); // Commands long onCmdPerspective(FXObject*,FXSelector,void*); long onUpdPerspective(FXObject*,FXSelector,void*); long onCmdParallel(FXObject*,FXSelector,void*); long onUpdParallel(FXObject*,FXSelector,void*); long onCmdFront(FXObject*,FXSelector,void*); long onUpdFront(FXObject*,FXSelector,void*); long onCmdBack(FXObject*,FXSelector,void*); long onUpdBack(FXObject*,FXSelector,void*); long onCmdLeft(FXObject*,FXSelector,void*); long onUpdLeft(FXObject*,FXSelector,void*); long onCmdRight(FXObject*,FXSelector,void*); long onUpdRight(FXObject*,FXSelector,void*); long onCmdTop(FXObject*,FXSelector,void*); long onUpdTop(FXObject*,FXSelector,void*); long onCmdBottom(FXObject*,FXSelector,void*); long onUpdBottom(FXObject*,FXSelector,void*); long onCmdResetView(FXObject*,FXSelector,void*); long onCmdFitView(FXObject*,FXSelector,void*); long onDNDEnter(FXObject*,FXSelector,void*); long onDNDLeave(FXObject*,FXSelector,void*); long onDNDMotion(FXObject*,FXSelector,void*); long onDNDDrop(FXObject*,FXSelector,void*); long onTipTimer(FXObject*,FXSelector,void*); long onCmdXYZDial(FXObject*,FXSelector,void*); long onUpdXYZDial(FXObject*,FXSelector,void*); long onCmdRollPitchYaw(FXObject*,FXSelector,void*); long onUpdRollPitchYaw(FXObject*,FXSelector,void*); long onCmdXYZScale(FXObject*,FXSelector,void*); long onUpdXYZScale(FXObject*,FXSelector,void*); long onUpdCurrent(FXObject*,FXSelector,void*); long onCmdCutSel(FXObject*,FXSelector,void*); long onCmdCopySel(FXObject*,FXSelector,void*); long onCmdPasteSel(FXObject*,FXSelector,void*); long onCmdDeleteSel(FXObject*,FXSelector,void*); long onUpdDeleteSel(FXObject*,FXSelector,void*); long onCmdBackColor(FXObject*,FXSelector,void*); long onUpdBackColor(FXObject*,FXSelector,void*); long onCmdGradientBackColor(FXObject*,FXSelector,void*); long onUpdGradientBackColor(FXObject*,FXSelector,void*); long onCmdAmbientColor(FXObject*,FXSelector,void*); long onUpdAmbientColor(FXObject*,FXSelector,void*); long onCmdLighting(FXObject*,FXSelector,void*); long onUpdLighting(FXObject*,FXSelector,void*); long onCmdFog(FXObject*,FXSelector,void*); long onUpdFog(FXObject*,FXSelector,void*); long onCmdDither(FXObject*,FXSelector,void*); long onUpdDither(FXObject*,FXSelector,void*); long onCmdFov(FXObject*,FXSelector,void*); long onUpdFov(FXObject*,FXSelector,void*); long onCmdZoom(FXObject*,FXSelector,void*); long onUpdZoom(FXObject*,FXSelector,void*); long onCmdLightAmbient(FXObject*,FXSelector,void*); long onUpdLightAmbient(FXObject*,FXSelector,void*); long onCmdLightDiffuse(FXObject*,FXSelector,void*); long onUpdLightDiffuse(FXObject*,FXSelector,void*); long onCmdLightSpecular(FXObject*,FXSelector,void*); long onUpdLightSpecular(FXObject*,FXSelector,void*); long onCmdTurbo(FXObject*,FXSelector,void*); long onUpdTurbo(FXObject*,FXSelector,void*); long onCmdPrintImage(FXObject*,FXSelector,void*); long onCmdPrintVector(FXObject*,FXSelector,void*); long onCmdLassoZoom(FXObject*,FXSelector,void*); long onCmdLassoSelect(FXObject*,FXSelector,void*); long onQueryHelp(FXObject*,FXSelector,void*); long onQueryTip(FXObject*,FXSelector,void*); virtual long onDefault(FXObject*,FXSelector,void*); public: // Projection modes enum { PARALLEL, // Parallel projection PERSPECTIVE // Perspective projection }; // Messages enum { ID_PERSPECTIVE=FXGLCanvas::ID_LAST, ID_PARALLEL, ID_FRONT, ID_BACK, ID_LEFT, ID_RIGHT, ID_TOP, ID_BOTTOM, ID_RESETVIEW, ID_FITVIEW, ID_TOP_COLOR, ID_BOTTOM_COLOR, ID_BACK_COLOR, ID_AMBIENT_COLOR, ID_LIGHT_AMBIENT, ID_LIGHT_DIFFUSE, ID_LIGHT_SPECULAR, ID_LIGHTING, ID_TURBO, ID_FOG, ID_DITHER, ID_SCALE_X, ID_SCALE_Y, ID_SCALE_Z, ID_DIAL_X, ID_DIAL_Y, ID_DIAL_Z, ID_ROLL, ID_PITCH, ID_YAW, ID_FOV, ID_ZOOM, ID_CUT_SEL, ID_COPY_SEL, ID_PASTE_SEL, ID_DELETE_SEL, ID_PRINT_IMAGE, ID_PRINT_VECTOR, ID_LASSO_ZOOM, ID_LASSO_SELECT, ID_LAST }; public: // Common DND type names static const FXchar objectTypeName[]; public: /// Construct GL viewer widget FXGLViewer(FXComposite* p,FXGLVisual *vis,FXObject* tgt=nullptr,FXSelector sel=0,FXuint opts=0,FXint x=0,FXint y=0,FXint w=0,FXint h=0); /// Construct GL viewer widget sharing display lists with another GL canvas FXGLViewer(FXComposite* p,FXGLVisual *vis,FXGLCanvas* share,FXObject* tgt=nullptr,FXSelector sel=0,FXuint opts=0,FXint x=0,FXint y=0,FXint w=0,FXint h=0); /// Construct GL viewer widget sharing context FXGLViewer(FXComposite* p,FXGLContext* ctx,FXObject* tgt=nullptr,FXSelector sel=0,FXuint opts=0,FXint x=0,FXint y=0,FXint w=0,FXint h=0); /// Create all of the server-side resources for this window virtual void create(); /// Detach server-side resources virtual void detach(); /// Perform layout virtual void layout(); /// Return size of pixel in world coordinates FXdouble worldPix() const { return worldpx; } /// Return size of pixel in model coordinates FXdouble modelPix() const { return modelpx; } /// Return a NULL-terminated list of all objects in the given rectangle, or NULL FXGLObject** lasso(FXint x1,FXint y1,FXint x2,FXint y2); /// Return a NULL-terminated list of all objects in the given rectangle, or NULL virtual FXGLObject** select(FXint x,FXint y,FXint w,FXint h); /// Perform a pick operation, returning the object at the given x,y position, or NULL virtual FXGLObject* pick(FXint x,FXint y); /// Change the model bounding box; this adjusts the viewer virtual FXbool setBounds(const FXRangef& box); /// Fit viewer to the given bounding box FXbool fitToBounds(const FXRangef& box); /// Return the viewer's viewport void getViewport(FXViewport& v) const; /// Translate eye-coordinate to screen coordinate void eyeToScreen(FXint& sx,FXint& sy,FXVec3f e); /// Translate screen coordinate to eye coordinate at the given depth FXVec3f screenToEye(FXint sx,FXint sy,FXfloat eyez=0.0f); /// Translate screen coordinate to eye coordinate at the target point depth FXVec3f screenToTarget(FXint sx,FXint sy); /// Translate world coordinate to eye coordinate FXVec3f worldToEye(FXVec3f w); /// Translate world coordinate to eye coordinate depth FXfloat worldToEyeZ(FXVec3f w); /// Translate eye coordinate to eye coordinate FXVec3f eyeToWorld(FXVec3f e); /// Calculate world coordinate vector from screen movement FXVec3f worldVector(FXint fx,FXint fy,FXint tx,FXint ty); /// Change default object material setting void setMaterial(const FXMaterial &mtl); /// Return default object material setting void getMaterial(FXMaterial &mtl) const; /// Change camera field of view angle (in degrees) void setFieldOfView(FXdouble fv); /// Return camera field of view angle FXdouble getFieldOfView() const { return fov; } /// Change camera zoom factor void setZoom(FXdouble zm); /// Return camera zoom factor FXdouble getZoom() const { return zoom; } /// Change target point distance void setDistance(FXdouble ed); /// Return target point distance FXdouble getDistance() const { return distance; } /// Change unequal model scaling factors void setScale(FXVec3f s); /// Return current scaling factors const FXVec3f& getScale() const { return scale; } /// Change camera orientation from quaternion void setOrientation(const FXQuatf& rot); /// Return current camera orientation quaternion const FXQuatf& getOrientation() const { return rotation; } /// Change object center (tranlation) void setCenter(FXVec3f cntr); /// Return object center const FXVec3f& getCenter() const { return center; } /// Translate object center void translate(FXVec3f vec); /// Return boresight vector FXbool getBoreVector(FXint sx,FXint sy,FXVec3f& point,FXVec3f& dir); /// Return eyesight vector FXVec3f getEyeVector() const; /// Return eye position FXVec3f getEyePosition() const; /// Change help text void setHelpText(const FXString& text); /// Return help text const FXString& getHelpText() const { return help; } /// Change tip text void setTipText(const FXString& text); /// Return tip text const FXString& getTipText() const { return tip; } /// Return the current transformation matrix const FXMat4f& getTransform() const { return transform; } /// Return the inverse of the current transformation matrix const FXMat4f& getInvTransform() const { return itransform; } /// Change the scene, i.e. the object being displayed. void setScene(FXGLObject* sc); /// Return the current scene object FXGLObject* getScene() const { return scene; } /// Change selection void setSelection(FXGLObject* sel); /// Return selection FXGLObject* getSelection() const { return selection; } /// Change the projection mode, PERSPECTIVE or PARALLEL void setProjection(FXuint proj); /// Return the projection mode FXuint getProjection() const { return projection; } /// Change both top and bottom background colors void setBackgroundColor(const FXVec4f& clr); /// Change top or bottom background color void setBackgroundColor(const FXVec4f& clr,FXbool bottom); /// Return top or bottom window background color const FXVec4f& getBackgroundColor(FXbool bottom) const { return background[bottom]; } /// Change global ambient light color void setAmbientColor(const FXVec4f& clr); /// Return global ambient light color const FXVec4f& getAmbientColor() const { return ambient; } /** * Read the pixels off the screen as array of FXColor; * this array can be directly passed to fxsaveBMP and other image * output routines. */ FXbool readPixels(FXColor*& buffer,FXint x,FXint y,FXint w,FXint h); /** * Read the feedback buffer containing the current scene, returning used * and allocated size. */ FXbool readFeedback(FXfloat*& buffer,FXint& used,FXint& size,FXint x,FXint y,FXint w,FXint h); /** * Change hidden-surface feedback buffer sorting algorithm. * This can be used for move/draw printed output depth sorting. */ void setZSortFunc(FXZSortFunc func){ zsortfunc=func; } /// Return hidden surface sorting function. FXZSortFunc getZSortFunc() const { return zsortfunc; } /** * Change the maximum hits, i.e. the maximum size of the pick buffer. * When set to less than or equal to zero, picking is essentially turned off. */ void setMaxHits(FXint maxh) { maxhits=maxh; } /// Return maximum pickbuffer size FXint getMaxHits() const { return maxhits; } /** * When drawing a GL object, if doesTurbo() is true, the object * may choose to perform a reduced complexity drawing as the user is * interactively manipulating; another update will be done later when * the full complexity drawing can be performed again. */ FXbool doesTurbo() const { return doesturbo; } /// Return turbo mode setting FXbool getTurboMode() const { return turbomode; } /// Set turbo mode void setTurboMode(FXbool turbo=true); /// Return light source settings void getLight(FXLight& lite) const; /// Change light source settings void setLight(const FXLight& lite); /// Save viewer to a stream virtual void save(FXStream& store) const; /// Load viewer from a stream virtual void load(FXStream& store); /// Destructor virtual ~FXGLViewer(); }; } #endif