390 lines
12 KiB
C++
390 lines
12 KiB
C++
/*
|
|
* 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 <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
|
|
*/
|
|
|
|
#ifndef VERTEX_MANAGER_H_
|
|
#define VERTEX_MANAGER_H_
|
|
|
|
#define GLM_FORCE_RADIANS
|
|
#include <glm/gtc/matrix_transform.hpp>
|
|
#include <glm/glm.hpp>
|
|
#include <gal/opengl/vertex_common.h>
|
|
#include <gal/color4d.h>
|
|
#include <stack>
|
|
#include <memory>
|
|
#include <wx/log.h>
|
|
|
|
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<VERTEX_CONTAINER> m_container;
|
|
/// GPU manager for data transfers and drawing operations
|
|
std::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[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_ */
|