summaryrefslogtreecommitdiff
path: root/include/gal/opengl/vertex_manager.h
blob: 56c84a6beb786bf5877cce1db25d2564830574dc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
/*
 * This program source code file is part of KiCad, a free EDA CAD application.
 *
 * Copyright (C) 2013 CERN
 * @author Maciej Suminski <maciej.suminski@cern.ch>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, you may find one here:
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * or you may search the http://www.gnu.org website for the version 2 license,
 * or you may write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 */

/**
 * @file vertex_manager.h
 * @brief Class to control vertex container and GPU with possibility of emulating old-style OpenGL
 * 1.0 state machine using modern OpenGL methods.
 */

#ifndef VERTEX_MANAGER_H_
#define VERTEX_MANAGER_H_

#define GLM_FORCE_RADIANS
#include <gal/opengl/glm/gtc/matrix_transform.hpp>
#include <gal/opengl/glm/glm.hpp>
#include <gal/opengl/vertex_common.h>
#include <gal/color4d.h>
#include <stack>
#include <boost/smart_ptr/shared_ptr.hpp>
#include <wx/log.h>

namespace KIGFX
{
class SHADER;
class VERTEX_ITEM;
class VERTEX_CONTAINER;
class GPU_MANAGER;

class VERTEX_MANAGER
{
public:
    /**
     * @brief Constructor.
     *
     * @param aCached says if vertices should be cached in GPU or system memory. For data that
     * does not change every frame, it is better to store vertices in GPU memory.
     */
    VERTEX_MANAGER( bool aCached );

    /**
     * Function Vertex()
     * adds a vertex with the given coordinates to the currently set item. Color & shader
     * parameters stored in aVertex are ignored, instead color & shader set by Color() and
     * Shader() functions are used. Vertex coordinates will have the current transformation
     * matrix applied.
     *
     * @param aVertex contains vertex coordinates.
     */
    inline void Vertex( const VERTEX& aVertex ) const
    {
        Vertex( aVertex.x, aVertex.y, aVertex.z );
    }

    /**
     * Function Vertex()
     * adds a vertex with the given coordinates to the currently set item. Vertex coordinates will
     * have the current transformation matrix applied.
     *
     * @param aX is the X coordinate of the new vertex.
     * @param aY is the Y coordinate of the new vertex.
     * @param aZ is the Z coordinate of the new vertex.
     */
    void Vertex( GLfloat aX, GLfloat aY, GLfloat aZ ) const;

    /**
     * Function Vertices()
     * adds one or more vertices to the currently set item. It takes advantage of allocating memory
     * in advance, so should be faster than adding vertices one by one. Color & shader
     * parameters stored in aVertices are ignored, instead color & shader set by Color() and
     * Shader() functions are used. All the vertex coordinates will have the current
     * transformation matrix applied.
     *
     * @param aVertices contains vertices to be added
     * @param aSize is the number of vertices to be added.
     */
    void Vertices( const VERTEX aVertices[], unsigned int aSize ) const;

    /**
     * Function Color()
     * changes currently used color that will be applied to newly added vertices.
     *
     * @param aColor is the new color.
     */
    inline void Color( const COLOR4D& aColor )
    {
        m_color[0] = aColor.r * 255.0;
        m_color[1] = aColor.g * 255.0;
        m_color[2] = aColor.b * 255.0;
        m_color[3] = aColor.a * 255.0;
    }

    /**
     * Function Color()
     * changes currently used color that will be applied to newly added vertices. It is the
     * equivalent of glColor4f() function.
     * @param aRed is the red component of the new color.
     * @param aGreen is the green component of the new color.
     * @param aBlue is the blue component of the new color.
     * @param aAlpha is the alpha component of the new color.
     */
    inline void Color( GLfloat aRed, GLfloat aGreen, GLfloat aBlue, GLfloat aAlpha )
    {
        m_color[0] = aRed   * 255.0;
        m_color[1] = aGreen * 255.0;
        m_color[2] = aBlue  * 255.0;
        m_color[3] = aAlpha * 255.0;
    }

    /**
     * Function Shader()
     * changes currently used shader and its parameters that will be applied to newly added
     * vertices. Parameters depend on shader, for more information have a look at shaders source
     * code.
     * @see SHADER_TYPE
     *
     * @param aShaderType is the a shader type to be applied.
     * @param aParam1 is the optional parameter for a shader.
     * @param aParam2 is the optional parameter for a shader.
     * @param aParam3 is the optional parameter for a shader.
     */
    inline void Shader( GLfloat aShaderType, GLfloat aParam1 = 0.0f,
                        GLfloat aParam2 = 0.0f, GLfloat aParam3 = 0.0f )
    {
        m_shader[0] = aShaderType;
        m_shader[1] = aParam1;
        m_shader[2] = aParam2;
        m_shader[3] = aParam3;
    }

    /**
     * Function Translate()
     * multiplies the current matrix by a translation matrix, so newly vertices will be
     * translated by the given vector. It is the equivalent of the glTranslatef() function.
     *
     * @param aX is the X coordinate of a translation vector.
     * @param aY is the X coordinate of a translation vector.
     * @param aZ is the X coordinate of a translation vector.
     */
    inline void Translate( GLfloat aX, GLfloat aY, GLfloat aZ )
    {
        m_transform = glm::translate( m_transform, glm::vec3( aX, aY, aZ ) );
    }

    /**
     * Function Rotate()
     * multiplies the current matrix by a rotation matrix, so the newly vertices will be
     * rotated by the given angles. It is the equivalent of the glRotatef() function.
     *
     * @param aAngle is the angle of rotation, in radians.
     * @param aX is a multiplier for the X axis
     * @param aY is a multiplier for the Y axis
     * @param aZ is a multiplier for the Z axis.
     */
    inline void Rotate( GLfloat aAngle, GLfloat aX, GLfloat aY, GLfloat aZ )
    {
        m_transform = glm::rotate( m_transform, aAngle, glm::vec3( aX, aY, aZ ) );
    }

    /**
     * Function Scale()
     * multiplies the current matrix by a scaling matrix, so the newly vertices will be
     * scaled by the given factors. It is the equivalent of the glScalef() function.
     *
     * @param aX is the X axis scaling factor.
     * @param aY is the Y axis scaling factor.
     * @param aZ is the Z axis scaling factor.
     */
    inline void Scale( GLfloat aX, GLfloat aY, GLfloat aZ )
    {
        m_transform = glm::scale( m_transform, glm::vec3( aX, aY, aZ ) );
    }

    /**
     * Function PushMatrix()
     * pushes the current transformation matrix stack. It is the equivalent of the glPushMatrix()
     * function.
     */
    inline void PushMatrix()
    {
        m_transformStack.push( m_transform );

        // Every transformation starts with PushMatrix
        m_noTransform = false;
    }

    /**
     * Function PopMatrix()
     * pops the current transformation matrix stack. It is the equivalent of the glPopMatrix()
     * function.
     */
    void PopMatrix()
    {
        wxASSERT( !m_transformStack.empty() );

        m_transform = m_transformStack.top();
        m_transformStack.pop();

        if( m_transformStack.empty() )
        {
            // We return back to the identity matrix, thus no vertex transformation is needed
            m_noTransform = true;
        }
    }

    /**
     * Function SetItem()
     * sets an item to start its modifications. After calling the function it is possible to add
     * vertices using function Add().
     *
     * @param aItem is the item that is going to store vertices in the container.
     */
    void SetItem( VERTEX_ITEM& aItem ) const;

    /**
     * Function FinishItem()
     * does the cleaning after adding an item.
     */
    void FinishItem() const;

    /**
     * Function FreeItem()
     * frees the memory occupied by the item, so it is no longer stored in the container.
     *
     * @param aItem is the item to be freed
     */
    void FreeItem( VERTEX_ITEM& aItem ) const;

    /**
     * Function ChangeItemColor()
     * changes the color of all vertices owned by an item.
     *
     * @param aItem is the item to change.
     * @param aColor is the new color to be applied.
     */
    void ChangeItemColor( const VERTEX_ITEM& aItem, const COLOR4D& aColor ) const;

    /**
     * Function ChangeItemDepth()
     * changes the depth of all vertices owned by an item.
     *
     * @param aItem is the item to change.
     * @param aDepth is the new color to be applied.
     */
    void ChangeItemDepth( const VERTEX_ITEM& aItem, GLfloat aDepth ) const;

    /**
     * Function GetVertices()
     * returns a pointer to the vertices owned by an item.
     *
     * @param aItem is the owner of vertices that are going to be returned.
     * @return Pointer to the vertices or NULL if the item is not stored at the container.
     */
    VERTEX* GetVertices( const VERTEX_ITEM& aItem ) const;

    const glm::mat4& GetTransformation() const
    {
        return m_transform;
    }

    /**
     * Function SetShader()
     * sets a shader program that is going to be used during rendering.
     * @param aShader is the object containing compiled and linked shader program.
     */
    void SetShader( SHADER& aShader ) const;

    /**
     * Function Clear()
     * removes all the stored vertices from the container.
     */
    void Clear() const;

    /**
     * Function BeginDrawing()
     * prepares buffers and items to start drawing.
     */
    void BeginDrawing() const;

    /**
     * Function DrawItem()
     * draws an item to the buffer.
     *
     * @param aItem is the item to be drawn.
     */
    void DrawItem( const VERTEX_ITEM& aItem ) const;

    /**
     * Function EndDrawing()
     * finishes drawing operations.
     */
    void EndDrawing() const;

protected:
    /**
     * Function putVertex()
     * applies all transformation to the given coordinates and store them at the specified target.
     *
     * @param aTarget is the place where the new vertex is going to be stored (it has to be
     * allocated first).
     * @param aX is the X coordinate of the new vertex.
     * @param aY is the Y coordinate of the new vertex.
     * @param aZ is the Z coordinate of the new vertex.
     */
    void putVertex( VERTEX& aTarget, GLfloat aX, GLfloat aY, GLfloat aZ ) const;

    /// Container for vertices, may be cached or noncached
    boost::shared_ptr<VERTEX_CONTAINER> m_container;
    /// GPU manager for data transfers and drawing operations
    boost::shared_ptr<GPU_MANAGER>      m_gpu;

    /// State machine variables
    /// True in case there is no need to transform vertices
    bool                    m_noTransform;
    /// Currently used transform matrix
    glm::mat4               m_transform;
    /// Stack of transformation matrices, used for Push/PopMatrix
    std::stack<glm::mat4>   m_transformStack;
    /// Currently used color
    GLubyte                 m_color[ColorStride];
    /// Currently used shader and its parameters
    GLfloat                 m_shader[ShaderStride];
};

} // namespace KIGFX

#endif /* VERTEX_MANAGER_H_ */