diff options
Diffstat (limited to 'include/gal/opengl/vertex_manager.h')
-rw-r--r-- | include/gal/opengl/vertex_manager.h | 347 |
1 files changed, 347 insertions, 0 deletions
diff --git a/include/gal/opengl/vertex_manager.h b/include/gal/opengl/vertex_manager.h new file mode 100644 index 0000000..56c84a6 --- /dev/null +++ b/include/gal/opengl/vertex_manager.h @@ -0,0 +1,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_ */ |