source: git/src/gla.h @ cdb5c7f

stereo-2025
Last change on this file since cdb5c7f was 2279fbed, checked in by Olly Betts <olly@…>, 4 months ago

Clean up OpenGL header inclusion

Probe for whether we have GL/glu.h or OpenGL/glu.h instead of checking
if APPLE is defined.

Fix the probe for GL/glext.h - we need to include gl.h first, but
had a hard-coded GL/gl.h which means this probe would always fail
on macOS.

  • Property mode set to 100644
File size: 9.8 KB
RevLine 
[56da40e]1//
2//  gla.h
3//
4//  Header file for the GLA abstraction layer.
5//
6//  Copyright (C) 2002 Mark R. Shinwell.
[9284d37]7//  Copyright (C) 2003-2025 Olly Betts
[56da40e]8//
9//  This program is free software; you can redistribute it and/or modify
10//  it under the terms of the GNU General Public License as published by
11//  the Free Software Foundation; either version 2 of the License, or
12//  (at your option) any later version.
13//
14//  This program is distributed in the hope that it will be useful,
15//  but WITHOUT ANY WARRANTY; without even the implied warranty of
16//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17//  GNU General Public License for more details.
18//
19//  You should have received a copy of the GNU General Public License
20//  along with this program; if not, write to the Free Software
[ecbc6c18]21//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
[56da40e]22//
23
[caa5fda]24#ifndef gla_h
25#define gla_h
26
[5627cbb]27#include <string>
[bae6a7c]28#include <vector>
29
30using namespace std;
31
[56da40e]32#include "wx.h"
[08253d9]33#include "vector3.h"
[56da40e]34
[1aa3fb7]35#include "glbitmapfont.h"
[1eeb55a]36
[2279fbed]37#ifdef HAVE_GL_GL_H
38# include <GL/gl.h>
39#elif defined HAVE_OPENGL_GL_H
40# include <OpenGL/gl.h>
41#endif
42
43#ifdef HAVE_GL_GLU_H
44# include <GL/glu.h>
45#elif defined HAVE_OPENGL_GLU_H
46# include <OpenGL/glu.h>
47#endif
48
[56da40e]49class GfxCore;
50
[5627cbb]51string GetGLSystemDescription();
[cc1a1d9]52
[d67450e]53// #define GLA_DEBUG
[1897247]54
[147847c]55typedef GLdouble glaCoord;
[56da40e]56
[ba828d4]57typedef GLfloat glaTexCoord;
[f336ab9]58
[aa048c3]59// Colours for drawing.  Don't reorder these!
60enum gla_colour {
61    col_BLACK = 0,
62    col_GREY,
63    col_LIGHT_GREY,
64    col_LIGHT_GREY_2,
65    col_DARK_GREY,
66    col_WHITE,
67    col_TURQUOISE,
68    col_GREEN,
69    col_INDICATOR_1,
70    col_INDICATOR_2,
71    col_YELLOW,
72    col_RED,
[f4c5932]73    col_BLUE,
[39b8117]74    col_MAGENTA,
[aa048c3]75    col_LAST // must be the last entry here
76};
77
[56da40e]78class GLAPen {
[aa048c3]79    friend class GLACanvas; // allow direct access to components
80
[a3f83057]81    double components[3] = { 0.0, 0.0, 0.0 }; // red, green, blue
[9cf3688]82
[56da40e]83public:
[a3f83057]84    GLAPen() {}
[56da40e]85
86    void SetColour(double red, double green, double blue); // arguments in range 0 to 1.0
[f383708]87    void Interpolate(const GLAPen&, double how_far);
[56da40e]88
[f7ea0e1]89    double GetRed() const;
90    double GetGreen() const;
91    double GetBlue() const;
[56da40e]92};
93
[db59b02]94class GLAList {
[a3f83057]95    GLuint gl_list = 0;
96    unsigned int flags = 0;
[db59b02]97  public:
[a3f83057]98    GLAList() { }
[db59b02]99    GLAList(GLuint gl_list_, unsigned int flags_)
100        : gl_list(gl_list_), flags(flags_) { }
101    operator bool() { return gl_list != 0; }
[620c0c9]102    bool need_to_generate();
103    void finalise(unsigned int list_flags);
104    bool DrawList() const;
[b3f1bbe]105    void invalidate_if(unsigned int mask) {
106        // If flags == NEVER_CACHE, the list won't be invalidated (unless
107        // mask is 0, which isn't a normal thing to pass).
108        if (flags & mask)
109            flags = 0;
110    }
[db59b02]111};
112
[56da40e]113class GLACanvas : public wxGLCanvas {
[b3f1bbe]114    friend class GLAList; // For flag values.
[620c0c9]115
[8c048fa]116    wxGLContext ctx;
117
[203d2a7]118#ifdef GLA_DEBUG
119    int m_Vertices;
120#endif
121
[dde4fe7]122    GLdouble modelview_matrix[16];
123    GLdouble projection_matrix[16];
124    GLint viewport[4];
125
[c5fc8eb]126    // Viewing volume diameter:
[a3f83057]127    glaCoord m_VolumeDiameter = 1.0;
[56da40e]128
129    // Parameters for plotting data:
[a3f83057]130    double m_Pan = 0.0, m_Tilt = 0.0;
131    double m_Scale = 0.0;
[d67450e]132    Vector3 m_Translation;
[56da40e]133
[9284d37]134    double z_stretch = 1.0;
135
[1aa3fb7]136    BitmapFont m_Font;
[d9b3270]137
[a3f83057]138    GLUquadric* m_Quadric = nullptr;
[a517825]139
[a3f83057]140    GLuint m_Texture = 0;
[cab6f11]141    GLuint m_BlobTexture;
[95ce35f]142    GLuint m_CrossTexture;
[a517825]143
[a3f83057]144    double alpha = 1.0;
[4a1cede]145
[a3f83057]146    bool m_SmoothShading = false;
147    bool m_Textured = false;
148    bool m_Perspective = false;
149    bool m_Fog = false;
150    bool m_AntiAlias = false;
[807f9dd]151    bool save_hints;
[fe075d7]152    enum { UNKNOWN = 0, POINT = 'P', LINES = 'L', SPRITE = 'S' };
[a3f83057]153    int blob_method = UNKNOWN;
154    int cross_method = UNKNOWN;
[1eeb55a]155
[a3f83057]156    int x_size = 0;
157    int y_size = 0;
[90430f2]158
[cf126fa]159    // wxHAS_DPI_INDEPENDENT_PIXELS is new in 3.1.6.  In older versions we just
160    // always do the scaling which is slightly less efficient for platforms
161    // where pixel coordinates don't scale with DPI.
162#if defined wxHAS_DPI_INDEPENDENT_PIXELS || \
163    !wxCHECK_VERSION(3,1,6)
164# define HAS_DPI_INDEPENDENT_PIXELS
165#endif
166
167#ifdef HAS_DPI_INDEPENDENT_PIXELS
[705adee9]168    double content_scale_factor = 1.0;
[2dacc8bd]169#else
170    static constexpr unsigned content_scale_factor = 1;
171#endif
[705adee9]172
[db59b02]173    vector<GLAList> drawing_lists;
[90430f2]174
175    enum {
176        INVALIDATE_ON_SCALE = 1,
177        INVALIDATE_ON_X_RESIZE = 2,
178        INVALIDATE_ON_Y_RESIZE = 4,
[2dacc8bd]179        INVALIDATE_ON_HIDPI = 8,
180        NEVER_CACHE = 16,
181        CACHED = 32
[90430f2]182    };
[a3f83057]183    mutable unsigned int list_flags = 0;
[bae6a7c]184
[807f9dd]185    wxString vendor, renderer;
186
187    bool CheckVisualFidelity(const unsigned char * target) const;
188
[56da40e]189public:
[84f1ed1]190    GLACanvas(wxWindow* parent, int id);
[56da40e]191    ~GLACanvas();
[2c8b64f]192
[caa5fda]193    static bool check_visual();
194
[1b12b82]195    void FirstShow();
196
[56da40e]197    void Clear();
[8a7f1c5]198    void ClearNative();
[56da40e]199    void StartDrawing();
200    void FinishDrawing();
201
[c5fc8eb]202    void SetVolumeDiameter(glaCoord diameter);
[56da40e]203    void SetDataTransform();
204    void SetIndicatorTransform();
[9cf3688]205
[d2fcc9b]206    void DrawList(unsigned int l);
[11fe902]207    void DrawListZPrepass(unsigned int l);
[147847c]208    void DrawList2D(unsigned int l, glaCoord x, glaCoord y, double rotation);
[b3f1bbe]209    void InvalidateList(unsigned int l) {
210        if (l < drawing_lists.size()) {
211            // Invalidate any existing cached list.
212            drawing_lists[l].invalidate_if(CACHED);
213        }
214    }
215
[d2fcc9b]216    virtual void GenerateList(unsigned int l) = 0;
[9cf3688]217
[aa048c3]218    void SetColour(const GLAPen& pen, double rgb_scale);
219    void SetColour(const GLAPen& pen);
[d1ce9bd]220    void SetColour(gla_colour colour, double rgb_scale);
[aa048c3]221    void SetColour(gla_colour colour);
[4a1cede]222    void SetAlpha(double new_alpha) { alpha = new_alpha; }
[aa048c3]223
[56da40e]224    void DrawText(glaCoord x, glaCoord y, glaCoord z, const wxString& str);
[1eeb55a]225    void DrawIndicatorText(int x, int y, const wxString& str);
[dbd50e2]226    void GetTextExtent(const wxString& str, int * x_ext, int * y_ext) const;
[9cf3688]227
[56da40e]228    void BeginQuadrilaterals();
229    void EndQuadrilaterals();
230    void BeginLines();
231    void EndLines();
[dde4fe7]232    void BeginTriangleStrip();
233    void EndTriangleStrip();
[56da40e]234    void BeginTriangles();
235    void EndTriangles();
236    void BeginPolyline();
237    void EndPolyline();
[0642381]238    void BeginPolyloop();
239    void EndPolyloop();
[45aa1d6]240    void BeginPolygon();
241    void EndPolygon();
[51eab3b]242    void BeginPoints();
243    void EndPoints();
[e633bb1]244    void BeginBlobs();
245    void EndBlobs();
[86fe6e4]246    void BeginCrosses();
247    void EndCrosses();
[9cf3688]248
[522e0bd]249    void DrawRectangle(gla_colour fill, gla_colour edge,
[d67450e]250                       glaCoord x0, glaCoord y0, glaCoord w, glaCoord h);
[aa048c3]251    void DrawShadedRectangle(const GLAPen & fill_bot, const GLAPen & fill_top,
252                             glaCoord x0, glaCoord y0, glaCoord w, glaCoord h);
253    void DrawCircle(gla_colour edge, gla_colour fill, glaCoord cx, glaCoord cy, glaCoord radius);
254    void DrawSemicircle(gla_colour edge, gla_colour fill, glaCoord cx, glaCoord cy, glaCoord radius, glaCoord start);
[9cf3688]255
[e633bb1]256    void DrawBlob(glaCoord x, glaCoord y, glaCoord z);
[81aea4e]257    void DrawBlob(glaCoord x, glaCoord y);
[86fe6e4]258    void DrawCross(glaCoord x, glaCoord y, glaCoord z);
[e633bb1]259    void DrawRing(glaCoord x, glaCoord y);
[9cf3688]260
[f336ab9]261    void PlaceVertex(const Vector3 & v, glaTexCoord tex_x, glaTexCoord tex_y) {
[b839829]262        PlaceVertex(v.GetX(), v.GetY(), v.GetZ(), tex_x, tex_y);
263    }
[d67450e]264    void PlaceVertex(const Vector3 & v) {
265        PlaceVertex(v.GetX(), v.GetY(), v.GetZ());
266    }
[56da40e]267    void PlaceVertex(glaCoord x, glaCoord y, glaCoord z);
[f336ab9]268    void PlaceVertex(glaCoord x, glaCoord y, glaCoord z,
269                     glaTexCoord tex_x, glaTexCoord tex_y);
[56da40e]270    void PlaceIndicatorVertex(glaCoord x, glaCoord y);
[203d2a7]271
[d67450e]272    void PlaceNormal(const Vector3 &v);
[9cf3688]273
[56da40e]274    void EnableDashedLines();
275    void DisableDashedLines();
276
[d67450e]277    void EnableSmoothPolygons(bool filled);
[1b12b82]278    void DisableSmoothPolygons();
279
[08253d9]280    void SetRotation(double pan, double tilt) {
281        m_Pan = pan;
282        m_Tilt = tilt;
283    }
[147847c]284    void SetScale(double);
[d67450e]285    void SetTranslation(const Vector3 &v) {
286        m_Translation = v;
287    }
288    void AddTranslation(const Vector3 &v) {
289        m_Translation += v;
290    }
291    const Vector3 & GetTranslation() const {
292        return m_Translation;
293    }
[56da40e]294    void AddTranslationScreenCoordinates(int dx, int dy);
295
[147847c]296    bool Transform(const Vector3 & v, glaCoord* x_out, glaCoord* y_out, glaCoord* z_out) const;
297    void ReverseTransform(double x, double y, glaCoord* x_out, glaCoord* y_out, glaCoord* z_out) const;
[56da40e]298
[9284d37]299    void SetZStretch(double z_stretch_) { z_stretch = z_stretch_; }
300
[1aa3fb7]301    int GetFontSize() const { return m_Font.get_font_size(); }
[087bc72]302
[d67450e]303    void ToggleSmoothShading();
304    bool GetSmoothShading() const { return m_SmoothShading; }
305
[147847c]306    double SurveyUnitsAcrossViewport() const;
[6abab84]307
[a517825]308    void ToggleTextured();
309    bool GetTextured() const { return m_Textured; }
310
[6abab84]311    void TogglePerspective() { m_Perspective = !m_Perspective; }
312    bool GetPerspective() const { return m_Perspective; }
[045e2af]313
[c60062d]314    void ToggleFog() { m_Fog = !m_Fog; }
315    bool GetFog() const { return m_Fog; }
316
[db452ae]317    void ToggleAntiAlias() { m_AntiAlias = !m_AntiAlias; }
318    bool GetAntiAlias() const { return m_AntiAlias; }
319
[1ada489]320    bool SaveScreenshot(const wxString & fnm, wxBitmapType type) const;
[aea4f8b]321
322    void ReadPixels(int width, int height, unsigned char * buf) const;
[f9ca87c]323
324    void PolygonOffset(bool on) const;
[90430f2]325
[2dacc8bd]326    int GetXSize() const {
327        list_flags |= INVALIDATE_ON_X_RESIZE;
328        return x_size;
329    }
330
331    int GetYSize() const {
332        list_flags |= INVALIDATE_ON_Y_RESIZE;
333        return y_size;
334    }
335
[cf126fa]336#ifdef HAS_DPI_INDEPENDENT_PIXELS
[2dacc8bd]337    double GetContentScaleFactor() const {
338        list_flags |= INVALIDATE_ON_HIDPI;
339        return content_scale_factor;
340    }
341
342    void UpdateContentScaleFactor();
343    void OnMove(wxMoveEvent & event);
344#else
345    // wxWindow::GetContentScaleFactor() will always return 1.0, so arrange
346    // things so it's a compile-time constant the compiler can optimise away.
[ecf9e9f2]347    // Use a macro so we can return unsigned instead of double without a lot
348    // of pain from trying to override a virtual method while changing the
349    // return type.
350# define GetContentScaleFactor() 1u
[2dacc8bd]351    void UpdateContentScaleFactor() { }
352#endif
[90430f2]353
354    void OnSize(wxSizeEvent & event);
[70acad9]355
356    glaCoord GetVolumeDiameter() const { return m_VolumeDiameter; }
[9071cf5]357
[705adee9]358    void ScaleMouseEvent(wxMouseEvent& e) const {
359        e.SetX(e.GetX() * content_scale_factor);
360        e.SetY(e.GetY() * content_scale_factor);
361    }
362
[9071cf5]363private:
364    DECLARE_EVENT_TABLE()
[56da40e]365};
[caa5fda]366
367#endif
Note: See TracBrowser for help on using the repository browser.