/* * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2013-2016 CERN * Copyright (C) 2020 KiCad Developers, see AUTHORS.txt for contributors. * * @author Maciej Suminski * * 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 */ #ifndef VERTEX_MANAGER_H_ #define VERTEX_MANAGER_H_ #define GLM_FORCE_RADIANS #include #include #include #include #include #include namespace KIGFX { class SHADER; class VERTEX_ITEM; class VERTEX_CONTAINER; class GPU_MANAGER; /** * Class to control vertex container and GPU with possibility of emulating old-style OpenGL * 1.0 state machine using modern OpenGL methods. */ class VERTEX_MANAGER { public: /** * @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 ); /** * Map vertex buffer. */ void Map(); /** * Unmap vertex buffer. */ void Unmap(); /** * Allocate space for vertices, so it will be used with subsequent Vertex() calls. * * @param aSize is the number of vertices that should be available in the reserved space. * @return True if successful, false otherwise. */ bool Reserve( unsigned int aSize ); /** * Add 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. * @return True if successful, false otherwise. */ inline bool Vertex( const VERTEX& aVertex ) { return Vertex( aVertex.x, aVertex.y, aVertex.z ); } /** * Add 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. * @return True if successful, false otherwise. */ bool Vertex( GLfloat aX, GLfloat aY, GLfloat aZ ); /** * Add a vertex with the given coordinates to the currently set item. * * Vertex coordinates will have the current transformation matrix applied. * * @param aXY are the XY coordinates of the new vertex. * @param aZ is the Z coordinate of the new vertex. * @return True if successful, false otherwise. */ bool Vertex( const VECTOR2D& aXY, GLfloat aZ ) { return Vertex( aXY.x, aXY.y, aZ ); } /** * Add 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. * @return True if successful, false otherwise. */ bool Vertices( const VERTEX aVertices[], unsigned int aSize ); /** * 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; } /** * Change 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; } /** * Change 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; } /** * Multiply 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 ) ); } /** * Multiply 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 ) ); } /** * Multiply 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 ) ); } /** * Push 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; } /** * Pop 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; } } /** * Set 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; /** * Clean after adding an item. */ void FinishItem() const; /** * Free 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; /** * Change 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; /** * Change 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; /** * Return 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; } /** * Set 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; /** * Remove all the stored vertices from the container. */ void Clear() const; /** * Prepare buffers and items to start drawing. */ void BeginDrawing() const; /** * Draw an item to the buffer. * * @param aItem is the item to be drawn. */ void DrawItem( const VERTEX_ITEM& aItem ) const; /** * Finish drawing operations. */ void EndDrawing() const; /** * Enable/disable Z buffer depth test. */ void EnableDepthTest( bool aEnabled ); protected: /** * Apply 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 std::shared_ptr m_container; /// GPU manager for data transfers and drawing operations std::shared_ptr 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 m_transformStack; /// Currently used color GLubyte m_color[COLOR_STRIDE]; /// Currently used shader and its parameters GLfloat m_shader[SHADER_STRIDE]; /// Currently reserved chunk to store vertices VERTEX* m_reserved; /// Currently available reserved space unsigned int m_reservedSpace; }; } // namespace KIGFX #endif /* VERTEX_MANAGER_H_ */