1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        oglstuff.h
3 // Purpose:     OpenGL manager for pyramid sample
4 // Author:      Manuel Martin
5 // Created:     2015/01/31
6 // Copyright:   (c) 2015 Manuel Martin
7 // Licence:     wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9 
10 #ifndef OGLSTUFF_H
11 #define OGLSTUFF_H
12 
13 #include <string>
14 #include <vector>
15 
16 #include "mathstuff.h"
17 
18 // This file allows access to OpenGL functions used in this sample.
19 #include "oglpfuncs.h"
20 
21 /*
22   ************  NOTES  *******************************************************
23   This is not an OGL tutorial, I mean, this is just a sample of how OGL stuff
24   may be arranged. I tried to keep it simple.
25   It's likely that the novice to OGL reads this sample, so here are some brief
26   notes:
27   * Starting with OpenGL >= 2.0 the user defines some special programs that are
28     going to be executed in the GPU, not in the CPU. These programs are called
29     "Shaders". Since OGL >= 3.2, and if a "Core Profile" context is set, the use
30     of shaders is the only way to make an OGL application.
31   * A program consists (at least) of a 'vertex shader' who operates on the
32     vertices that define the primitive (a triangle, a line, etc) and a 'fragment
33     shader' which deals with fragments (points) interpolated from the previously
34     processed vertices in the vertex shader.
35   * Shaders must be compiled and linked, both operations are done on the GPU.
36   * Shaders are written in the GLSL language, that looks like C, but it isn't C.
37   * Data (vertices, textures) are stored in GPU memory, so they don't need to be
38     loaded each time the scene must be redrawn.
39   * Rotations and translations are matrix operations that the GPU may do in the
40     [vertex]shaders. The user must define the needed matrices.
41   * A vertex shader defines special vars ("attributes") used for reading the
42     data from the GPU buffers. Other special vars ("uniforms") are used for
43     values that don't change with each vertex (i.e. the matrices).
44   * The relationship between a data buffer and the input attributes in a vertex
45     shader can be saved in a "Vertex Array Object" (VAO).
46 
47   I use several classes for typical OGL jobs: Shaders, Data, Camera.
48   Because different GPU cards may behave on their own, I also use very often
49   an error-helper. It will inform of the point where something went wrong.
50 
51   I decided to keep apart all of this from wxWidgets. You won't find anything
52   related to wxWidgets in the oglstuff[.h][.cpp] files.
53   That's why I use std::vector and std:string instead of those provided by wx.
54 */
55 
56 
57 // Define our own GL errors
58 enum
59 {
60     myoglERR_CLEAR = 0,
61     myoglERR_JUSTLOG,
62 
63     myoglERR_SHADERCREATE,
64     myoglERR_SHADERCOMPILE,
65     myoglERR_SHADERLINK,
66     myoglERR_SHADERLOCATION,
67 
68     myoglERR_BUFFER,
69     myoglERR_TEXTIMAGE,
70 
71     myoglERR_DRAWING_TRI,
72     myoglERR_DRAWING_STR
73 };
74 
75 // Used to handle GL errors in other part of the app.
76 typedef void myOGLErrHandler(int err, int glerr, const GLchar* glMsg);
77 
78 // For shader attributes
79 struct shaVars
80 {
81     GLuint loc; //The attribute "location", some kind of index in the shader
82     std::string name; //The name of the attribute
83 };
84 
85 typedef std::vector<shaVars> shaVars_v;
86 
87 // For shader code
88 struct shaShas
89 {
90     GLuint shaId;
91     GLenum typeSha; //The type of shader
92     const GLchar* scode; //The NULL terminated GLSL code
93 };
94 
95 typedef std::vector<shaShas> shaShas_v;
96 
97 
98 //-----------------------------------------------------------------------------
99 // This object builds a GPU program by joining several shaders.
100 class myOGLShaders
101 {
102 public:
103     myOGLShaders();
104     ~myOGLShaders();
105 
106     void Init();
107     bool Use();
108     void StopUse();
109     void CleanUp();
110 
111     void AddCode(const GLchar* shaString, GLenum shaType);
112     void AddAttrib(const std::string& name);
113     void AddUnif(const std::string& name);
114     GLuint GetAttribLoc(const std::string& name);
115     GLuint GetUnifLoc(const std::string& name);
116     // Disable generic vertex attribute array
117     void DisableGenericVAA();
118 
119 private:
120     void SetAttribLocations();
121     bool AskUnifLocations();
122     bool Compile(GLuint shaId);
123     bool LinkProg(GLuint proId);
124 
125     shaVars_v m_shaAttrib; // 'attributes' names and locations
126     shaVars_v m_shaUnif; // 'uniforms' names and locations
127     shaShas_v m_shaCode; // shaders code and their types
128     GLuint m_proId; // program Id
129 
130     bool m_SHAinitializated;
131 };
132 
133 //-----------------------------------------------------------------------------
134 // A "point light"
135 class myLight
136 {
137 public:
myLight()138     myLight() {}
~myLight()139     ~myLight() {}
140 
141     void Set(const myVec3& position, GLfloat intensity,
142              GLfloat R, GLfloat G, GLfloat B);
143     // Return position and intensity
GetFLightPos()144     const GLfloat* GetFLightPos() const
145         { return m_PosAndIntensisty; }
146     // Return colour
GetFLightColour()147     const GLfloat* GetFLightColour() const
148         { return m_Colour; }
149 
150 private:
151     // Light position and intensity
152     GLfloat m_PosAndIntensisty[4];
153     // Light colour
154     GLfloat m_Colour[3];
155 };
156 
157 //-----------------------------------------------------------------------------
158 // An object for triangles
159 class myOGLTriangles
160 {
161 public:
162     myOGLTriangles();
163     ~myOGLTriangles();
164 
165     // Clean up
166     void Clear();
167     // Load data into the GPU
168     void SetBuffers(myOGLShaders* theShader, GLsizei nuPoints, GLsizei nuTriangs,
169                     const GLfloat* vert, const GLfloat* colo,
170                     const GLfloat* norm, const GLushort* indices);
171 
172     //Draw the triangles
173     void Draw(const GLfloat* unifMvp, const GLfloat* unifToVw,
174               const myLight* theLight);
175 
176 private:
177     GLsizei m_nuTriangs;
178     // Buffers ids
179     GLuint m_bufVertId;
180     GLuint m_bufColNorId;
181     GLuint m_bufIndexId;
182     // Vertex Arrays Object
183     GLuint m_triangVAO;
184     // GPU Program used to draw the triangles
185     myOGLShaders* m_triangShaders;
186 };
187 
188 //-----------------------------------------------------------------------------
189 // An object for strings
190 class myOGLString
191 {
192 public:
193     myOGLString();
194     ~myOGLString();
195 
196     // Clean up
197     void Clear();
198     // Load data into the GPU
199     void SetStringWithVerts(myOGLShaders* theShader,
200                              const unsigned char* tImage, int tWidth, int tHeigh,
201                              const GLfloat* vert, const GLfloat* norm);
202     // Draw the string
203     void Draw(const GLfloat* unifMvp, const GLfloat* unifToVw,
204               const myLight* theLight);
205 
206 
207 private:
208     GLuint m_bufPosId;    // Buffer id
209     GLuint m_stringVAO;   // Vertex Arrays Object
210     GLuint m_textureUnit; // The context unit
211     GLuint m_textureId;   // Texture name
212     // GPU Program used to draw the texture
213     myOGLShaders* m_stringShaders;
214 };
215 
216 //-----------------------------------------------------------------------------
217 // An object for the immutable string
218 class myOGLImmutString : public myOGLString
219 {
220 public:
myOGLImmutString()221     myOGLImmutString(){}
~myOGLImmutString()222     ~myOGLImmutString(){}
223 
224     // Load data into the GPU
225     void SetImmutString(myOGLShaders* theShader,
226                         const unsigned char* tImage, int tWidth, int tHeigh);
227     // Update orthogonal projection matrix
228     void SetOrtho(int winWidth, int winHeight);
229     // The transformation matrix
GetFloatMVP()230     const GLfloat* GetFloatMVP() { return m_fOrtho; }
231 
232 private:
233     double m_dOrtho[16]; // The orthogonal projection matrix
234     GLfloat m_fOrtho[16]; // Same as float
235 };
236 
237 //-----------------------------------------------------------------------------
238 // The "camera", or the point of view
239 class myOGLCamera
240 {
241 public:
242     myOGLCamera();
~myOGLCamera()243     ~myOGLCamera() {}
244 
245     // Initial positions
246     void InitPositions();
247     // When the size of the window changes
248     void ViewSizeChanged(int newWidth, int newHeight);
249     // The whole transformation matrix
250     const GLfloat* GetFloatMVP();
251     // The 'To View Space' transformation matrix
252     const GLfloat* GetFloatToVw();
253     // The camera position
GetPosition()254     myVec3 GetPosition() {return m_camPosition;}
255 
256     // Simulates a virtual trackball and rotates the 'world'
257     void MouseRotation(int fromX, int fromY, int toX, int toY);
258     double GetTrackballZ(double x, double y, double r);
259 
260     // The used matrices
261     double m_dMode[16]; // The model matrix, rotation in this sample
262     double m_dView[16]; // The view matrix
263     double m_dProj[16]; // The projection matrix
264     double m_dMVP[16];  // The whole transform matrix
265     double m_dToVw[16]; // The 'to View' transform matrix
266     // GLFloat versions. GLdouble is available since OGL 4.0, and we use 3.2
267     GLfloat m_fMVP[16];
268     GLfloat m_fToVw[16];
269 private:
270     bool m_needMVPUpdate;
271 
272     void UpdateMatrices();
273 
274     // Coordinates in model space
275     myVec3 m_centerOfWorld;
276     double m_radiusOfWorld;
277     myVec3 m_camPosition;
278     myVec3 m_camTarget;
279     myVec3 m_camUp;
280 
281     // Window size in pixels
282     int m_winWidth;
283     int m_winHeight;
284 
285     // Parameters for the projection
286     double m_fov;
287     double m_nearD;
288     double m_farD;
289 };
290 
291 //-----------------------------------------------------------------------------
292 // General manager
293 class myOGLManager
294 {
295 public:
296     myOGLManager(myOGLErrHandler* extErrHnd = NULL);
297     ~myOGLManager();
298 
299     // Constants, prototypes and pointers to OGL functions
300     static bool Init();
301     // Strings describing the current GL connection
302     const GLubyte* GetGLVersion();
303     const GLubyte* GetGLVendor();
304     const GLubyte* GetGLRenderer();
305 
306     // Load data into the GPU
307     void SetShadersAndTriangles();
308     // Load the texture for the string in the pyramid
309     void SetStringOnPyr(const unsigned char* strImage, int iWidth, int iHeigh);
310     // Load the texture for the immutable string
311     void SetImmutableString(const unsigned char* strImage, int iWidth, int iHeigh);
312 
313     // For window size change
314     void SetViewport(int x, int y, int width, int height);
315 
316     void Render(); // Total rendering
317 
318     // Action events in OpenGL win coordinates (bottom is y=0)
319     void OnMouseButDown(int posX, int posY);
320     void OnMouseRotDragging(int posX, int posY);
321 
322 private:
323     // Members
324     myOGLShaders   m_TriangShaders;
325     myOGLShaders   m_StringShaders;
326     myOGLShaders   m_ImmutStringSha;
327     myLight        m_Light;
328     myOGLCamera    m_Camera;
329 
330     myOGLTriangles    m_Triangles;
331     myOGLString       m_StringOnPyr;
332     myOGLImmutString  m_ImmString;
333 
334     // For mouse event
335     int m_mousePrevX;
336     int m_mousePrevY;
337 };
338 
339 #endif //OGLSTUFF_H
340 
341