source: git/src/gla.h @ 8d74d05

stereo-2025
Last change on this file since 8d74d05 was 9284d37, checked in by Olly Betts <olly@…>, 4 months ago

Allow exaggerating Z in aven

Add a spin control to the toolbar which allows setting a Z scale
factor from 0.1 and 10.0.

Fixes #49

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