Update copyright headers
[qt:qt.git] / demos / boxes / glbuffers.h
1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the demonstration applications of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file.  Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #ifndef GLBUFFERS_H
43 #define GLBUFFERS_H
44
45 //#include <GL/glew.h>
46 #include "glextensions.h"
47
48 #include <QtGui>
49 #include <QtOpenGL>
50
51 #define BUFFER_OFFSET(i) ((char*)0 + (i))
52 #define SIZE_OF_MEMBER(cls, member) sizeof(static_cast<cls *>(0)->member)
53
54 #define GLBUFFERS_ASSERT_OPENGL(prefix, assertion, returnStatement)                         \
55 if (m_failed || !(assertion)) {                                                             \
56     if (!m_failed) qCritical(prefix ": The necessary OpenGL functions are not available."); \
57     m_failed = true;                                                                        \
58     returnStatement;                                                                        \
59 }
60
61 void qgluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar);
62
63 QT_BEGIN_NAMESPACE
64 class QMatrix4x4;
65 QT_END_NAMESPACE
66
67 class GLTexture
68 {
69 public:
70     GLTexture();
71     virtual ~GLTexture();
72     virtual void bind() = 0;
73     virtual void unbind() = 0;
74     virtual bool failed() const {return m_failed;}
75 protected:
76     GLuint m_texture;
77     bool m_failed;
78 };
79
80 class GLFrameBufferObject
81 {
82 public:
83     friend class GLRenderTargetCube;
84     // friend class GLRenderTarget2D;
85
86     GLFrameBufferObject(int width, int height);
87     virtual ~GLFrameBufferObject();
88     bool isComplete();
89     virtual bool failed() const {return m_failed;}
90 protected:
91     void setAsRenderTarget(bool state = true);
92     GLuint m_fbo;
93     GLuint m_depthBuffer;
94     int m_width, m_height;
95     bool m_failed;
96 };
97
98 class GLTexture2D : public GLTexture
99 {
100 public:
101     GLTexture2D(int width, int height);
102     GLTexture2D(const QString& fileName, int width = 0, int height = 0);
103     void load(int width, int height, QRgb *data);
104     virtual void bind();
105     virtual void unbind();
106 };
107
108 class GLTexture3D : public GLTexture
109 {
110 public:
111     GLTexture3D(int width, int height, int depth);
112     // TODO: Implement function below
113     //GLTexture3D(const QString& fileName, int width = 0, int height = 0);
114     void load(int width, int height, int depth, QRgb *data);
115     virtual void bind();
116     virtual void unbind();
117 };
118
119 class GLTextureCube : public GLTexture
120 {
121 public:
122     GLTextureCube(int size);
123     GLTextureCube(const QStringList& fileNames, int size = 0);
124     void load(int size, int face, QRgb *data);
125     virtual void bind();
126     virtual void unbind();
127 };
128
129 // TODO: Define and implement class below
130 //class GLRenderTarget2D : public GLTexture2D
131
132 class GLRenderTargetCube : public GLTextureCube
133 {
134 public:
135     GLRenderTargetCube(int size);
136     // begin rendering to one of the cube's faces. 0 <= face < 6
137     void begin(int face);
138     // end rendering
139     void end();
140     virtual bool failed() {return m_failed || m_fbo.failed();}
141
142     static void getViewMatrix(QMatrix4x4& mat, int face);
143     static void getProjectionMatrix(QMatrix4x4& mat, float nearZ, float farZ);
144 private:
145     GLFrameBufferObject m_fbo;
146 };
147
148 struct VertexDescription
149 {
150     enum
151     {
152         Null = 0, // Terminates a VertexDescription array
153         Position,
154         TexCoord,
155         Normal,
156         Color,
157     };
158     int field; // Position, TexCoord, Normal, Color
159     int type; // GL_FLOAT, GL_UNSIGNED_BYTE
160     int count; // number of elements
161     int offset; // field's offset into vertex struct
162     int index; // 0 (unused at the moment)
163 };
164
165 // Implementation of interleaved buffers.
166 // 'T' is a struct which must include a null-terminated static array
167 // 'VertexDescription* description'.
168 // Example:
169 /*
170 struct Vertex
171 {
172     GLfloat position[3];
173     GLfloat texCoord[2];
174     GLfloat normal[3];
175     GLbyte color[4];
176     static VertexDescription description[];
177 };
178
179 VertexDescription Vertex::description[] = {
180     {VertexDescription::Position, GL_FLOAT, SIZE_OF_MEMBER(Vertex, position) / sizeof(GLfloat), offsetof(Vertex, position), 0},
181     {VertexDescription::TexCoord, GL_FLOAT, SIZE_OF_MEMBER(Vertex, texCoord) / sizeof(GLfloat), offsetof(Vertex, texCoord), 0},
182     {VertexDescription::Normal, GL_FLOAT, SIZE_OF_MEMBER(Vertex, normal) / sizeof(GLfloat), offsetof(Vertex, normal), 0},
183     {VertexDescription::Color, GL_BYTE, SIZE_OF_MEMBER(Vertex, color) / sizeof(GLbyte), offsetof(Vertex, color), 0},
184     {VertexDescription::Null, 0, 0, 0, 0},
185 };
186 */
187 template<class T>
188 class GLVertexBuffer
189 {
190 public:
191     GLVertexBuffer(int length, const T *data = 0, int mode = GL_STATIC_DRAW)
192         : m_length(0)
193         , m_mode(mode)
194         , m_buffer(0)
195         , m_failed(false)
196     {
197         GLBUFFERS_ASSERT_OPENGL("GLVertexBuffer::GLVertexBuffer", glGenBuffers && glBindBuffer && glBufferData, return)
198
199                 glGenBuffers(1, &m_buffer);
200                 glBindBuffer(GL_ARRAY_BUFFER, m_buffer);
201                 glBufferData(GL_ARRAY_BUFFER, (m_length = length) * sizeof(T), data, mode);
202     }
203
204     ~GLVertexBuffer()
205     {
206         GLBUFFERS_ASSERT_OPENGL("GLVertexBuffer::~GLVertexBuffer", glDeleteBuffers, return)
207
208         glDeleteBuffers(1, &m_buffer);
209     }
210
211     void bind()
212     {
213         GLBUFFERS_ASSERT_OPENGL("GLVertexBuffer::bind", glBindBuffer, return)
214
215         glBindBuffer(GL_ARRAY_BUFFER, m_buffer);
216         for (VertexDescription *desc = T::description; desc->field != VertexDescription::Null; ++desc) {
217             switch (desc->field) {
218             case VertexDescription::Position:
219                 glVertexPointer(desc->count, desc->type, sizeof(T), BUFFER_OFFSET(desc->offset));
220                 glEnableClientState(GL_VERTEX_ARRAY);
221                 break;
222             case VertexDescription::TexCoord:
223                 glTexCoordPointer(desc->count, desc->type, sizeof(T), BUFFER_OFFSET(desc->offset));
224                 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
225                 break;
226             case VertexDescription::Normal:
227                 glNormalPointer(desc->type, sizeof(T), BUFFER_OFFSET(desc->offset));
228                 glEnableClientState(GL_NORMAL_ARRAY);
229                 break;
230             case VertexDescription::Color:
231                 glColorPointer(desc->count, desc->type, sizeof(T), BUFFER_OFFSET(desc->offset));
232                 glEnableClientState(GL_COLOR_ARRAY);
233                 break;
234             default:
235                 break;
236             }
237         }
238     }
239
240     void unbind()
241     {
242         GLBUFFERS_ASSERT_OPENGL("GLVertexBuffer::unbind", glBindBuffer, return)
243
244         glBindBuffer(GL_ARRAY_BUFFER, 0);
245         for (VertexDescription *desc = T::description; desc->field != VertexDescription::Null; ++desc) {
246             switch (desc->field) {
247             case VertexDescription::Position:
248                 glDisableClientState(GL_VERTEX_ARRAY);
249                 break;
250             case VertexDescription::TexCoord:
251                 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
252                 break;
253             case VertexDescription::Normal:
254                 glDisableClientState(GL_NORMAL_ARRAY);
255                 break;
256             case VertexDescription::Color:
257                 glDisableClientState(GL_COLOR_ARRAY);
258                 break;
259             default:
260                 break;
261             }
262         }
263     }
264
265     int length() const {return m_length;}
266
267     T *lock()
268     {
269         GLBUFFERS_ASSERT_OPENGL("GLVertexBuffer::lock", glBindBuffer && glMapBuffer, return 0)
270
271         glBindBuffer(GL_ARRAY_BUFFER, m_buffer);
272         //glBufferData(GL_ARRAY_BUFFER, m_length, NULL, m_mode);
273         GLvoid* buffer = glMapBuffer(GL_ARRAY_BUFFER, GL_READ_WRITE);
274         m_failed = (buffer == 0);
275         return reinterpret_cast<T *>(buffer);
276     }
277
278     void unlock()
279     {
280         GLBUFFERS_ASSERT_OPENGL("GLVertexBuffer::unlock", glBindBuffer && glUnmapBuffer, return)
281
282         glBindBuffer(GL_ARRAY_BUFFER, m_buffer);
283         glUnmapBuffer(GL_ARRAY_BUFFER);
284     }
285
286     bool failed()
287     {
288         return m_failed;
289     }
290
291 private:
292     int m_length, m_mode;
293     GLuint m_buffer;
294     bool m_failed;
295 };
296
297 template<class T>
298 class GLIndexBuffer
299 {
300 public:
301     GLIndexBuffer(int length, const T *data = 0, int mode = GL_STATIC_DRAW)
302         : m_length(0)
303         , m_mode(mode)
304         , m_buffer(0)
305         , m_failed(false)
306     {
307         GLBUFFERS_ASSERT_OPENGL("GLIndexBuffer::GLIndexBuffer", glGenBuffers && glBindBuffer && glBufferData, return)
308
309         glGenBuffers(1, &m_buffer);
310         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_buffer);
311         glBufferData(GL_ELEMENT_ARRAY_BUFFER, (m_length = length) * sizeof(T), data, mode);
312     }
313
314     ~GLIndexBuffer()
315     {
316         GLBUFFERS_ASSERT_OPENGL("GLIndexBuffer::~GLIndexBuffer", glDeleteBuffers, return)
317
318         glDeleteBuffers(1, &m_buffer);
319     }
320
321     void bind()
322     {
323         GLBUFFERS_ASSERT_OPENGL("GLIndexBuffer::bind", glBindBuffer, return)
324
325         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_buffer);
326     }
327
328     void unbind()
329     {
330         GLBUFFERS_ASSERT_OPENGL("GLIndexBuffer::unbind", glBindBuffer, return)
331
332         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
333     }
334
335     int length() const {return m_length;}
336
337     T *lock()
338     {
339         GLBUFFERS_ASSERT_OPENGL("GLIndexBuffer::lock", glBindBuffer && glMapBuffer, return 0)
340
341         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_buffer);
342         GLvoid* buffer = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_READ_WRITE);
343         m_failed = (buffer == 0);
344         return reinterpret_cast<T *>(buffer);
345     }
346
347     void unlock()
348     {
349         GLBUFFERS_ASSERT_OPENGL("GLIndexBuffer::unlock", glBindBuffer && glUnmapBuffer, return)
350
351         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_buffer);
352         glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
353     }
354
355     bool failed()
356     {
357         return m_failed;
358     }
359
360 private:
361     int m_length, m_mode;
362     GLuint m_buffer;
363     bool m_failed;
364 };
365
366 #endif