vertex_manager.h 11.4 KB
Newer Older
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
/*
 * 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>

43
namespace KIGFX
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
{
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;

235 236 237 238 239 240
    /**
     * Function FinishItem()
     * does the cleaning after adding an item.
     */
    void FinishItem() const;

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
    /**
     * 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];
};

345
} // namespace KIGFX
346 347

#endif /* VERTEX_MANAGER_H_ */