Added VBO_CONTAINER as a faster storage for vertices (OPENGL_GAL), tuned for exchanging data with GPU.
Removed a few unnecessary variables and fields from OPENGL_GAL. Added function GAL::ClearCache() for freeing memory used by cached items. Fixed a few memory leaks (tesselator, PAINTER's settings & VIEW_ITEM's groups). Changed a few functions into inlines.
This commit is contained in:
parent
876bf75d89
commit
cd517f67db
|
@ -21,6 +21,7 @@ set(GAL_SRCS
|
|||
gal/opengl/opengl_gal.cpp
|
||||
gal/opengl/shader.cpp
|
||||
gal/opengl/vbo_item.cpp
|
||||
gal/opengl/vbo_container.cpp
|
||||
gal/cairo/cairo_gal.cpp
|
||||
view/wx_view_controls.cpp
|
||||
)
|
||||
|
|
|
@ -99,10 +99,7 @@ CAIRO_GAL::~CAIRO_GAL()
|
|||
delete cursorPixels;
|
||||
delete cursorPixelsSaved;
|
||||
|
||||
for( int i = groups.size() - 1; i >= 0; --i )
|
||||
{
|
||||
DeleteGroup( i );
|
||||
}
|
||||
ClearCache();
|
||||
|
||||
deleteBitmaps();
|
||||
}
|
||||
|
@ -687,13 +684,22 @@ void CAIRO_GAL::EndGroup()
|
|||
}
|
||||
|
||||
|
||||
void CAIRO_GAL::ClearCache()
|
||||
{
|
||||
for( int i = groups.size() - 1; i >= 0; --i )
|
||||
{
|
||||
DeleteGroup( i );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CAIRO_GAL::DeleteGroup( int aGroupNumber )
|
||||
{
|
||||
storePath();
|
||||
|
||||
// Delete the Cairo paths
|
||||
for( std::deque<GroupElement>::iterator it = groups[aGroupNumber].begin(), end = groups[aGroupNumber].end();
|
||||
it != end; ++it )
|
||||
std::deque<GroupElement>::iterator it, end;
|
||||
for( it = groups[aGroupNumber].begin(), end = groups[aGroupNumber].end(); it != end; ++it )
|
||||
{
|
||||
if( it->command == CMD_FILL_PATH || it->command == CMD_STROKE_PATH )
|
||||
{
|
||||
|
|
|
@ -29,8 +29,8 @@
|
|||
#include <cmath>
|
||||
|
||||
#include <gal/opengl/opengl_gal.h>
|
||||
#include <gal/opengl/vbo_container.h>
|
||||
#include <gal/definitions.h>
|
||||
#include <gal/opengl/glm/gtc/matrix_transform.hpp>
|
||||
|
||||
#include <wx/log.h>
|
||||
#include <macros.h>
|
||||
|
@ -78,7 +78,6 @@ OPENGL_GAL::OPENGL_GAL( wxWindow* aParent, wxEvtHandler* aMouseListener,
|
|||
isVboInitialized = false;
|
||||
vboNeedsUpdate = false;
|
||||
curVboItem = NULL;
|
||||
vboSize = 0;
|
||||
transform = glm::mat4( 1.0f ); // Identity matrix
|
||||
|
||||
SetSize( parentSize );
|
||||
|
@ -107,12 +106,26 @@ OPENGL_GAL::OPENGL_GAL( wxWindow* aParent, wxEvtHandler* aMouseListener,
|
|||
Connect( wxEVT_ENTER_WINDOW, wxMouseEventHandler( OPENGL_GAL::skipMouseEvent ) );
|
||||
#endif
|
||||
|
||||
vboContainer = new VBO_CONTAINER;
|
||||
|
||||
// Tesselator initialization
|
||||
tesselator = gluNewTess();
|
||||
InitTesselatorCallbacks( tesselator );
|
||||
gluTessProperty( tesselator, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_POSITIVE );
|
||||
|
||||
if( !isUseShader )
|
||||
{
|
||||
// (3 vertices per triangle) * (2 items [circle&semicircle]) * (number of points per item)
|
||||
precomputedContainer = new VBO_CONTAINER( 3 * 2 * CIRCLE_POINTS );
|
||||
|
||||
// Compute the unit circles, used for speed up of the circle drawing
|
||||
verticesCircle = new VBO_ITEM( precomputedContainer );
|
||||
computeUnitCircle();
|
||||
verticesCircle->Finish();
|
||||
|
||||
verticesSemiCircle = new VBO_ITEM( precomputedContainer );
|
||||
computeUnitSemiCircle();
|
||||
//computeUnitArcs(); // TODO remove? it is not used anywhere
|
||||
verticesSemiCircle->Finish();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -121,6 +134,13 @@ OPENGL_GAL::~OPENGL_GAL()
|
|||
{
|
||||
glFlush();
|
||||
|
||||
if( !isUseShader )
|
||||
{
|
||||
delete verticesCircle;
|
||||
delete verticesSemiCircle;
|
||||
delete precomputedContainer;
|
||||
}
|
||||
|
||||
// Delete the buffers
|
||||
if( isFrameBufferInitialized )
|
||||
{
|
||||
|
@ -128,16 +148,13 @@ OPENGL_GAL::~OPENGL_GAL()
|
|||
deleteFrameBuffer( &frameBufferBackup, &depthBufferBackup, &textureBackup );
|
||||
}
|
||||
|
||||
gluDeleteTess( tesselator );
|
||||
|
||||
if( isVboInitialized )
|
||||
{
|
||||
std::deque<VBO_ITEM*>::iterator it, end;
|
||||
|
||||
for( it = vboItems.begin(), end = vboItems.end(); it != end; it++ )
|
||||
{
|
||||
delete *it;
|
||||
}
|
||||
|
||||
ClearCache();
|
||||
deleteVertexBufferObjects();
|
||||
delete vboContainer;
|
||||
}
|
||||
|
||||
delete glContext;
|
||||
|
@ -241,8 +258,8 @@ void OPENGL_GAL::initFrameBuffers()
|
|||
void OPENGL_GAL::initVertexBufferObjects()
|
||||
{
|
||||
// Generate buffers for vertices and indices
|
||||
glGenBuffers( 1, &curVboVertId );
|
||||
glGenBuffers( 1, &curVboIndId );
|
||||
glGenBuffers( 1, &vboVertices );
|
||||
glGenBuffers( 1, &vboIndices );
|
||||
|
||||
isVboInitialized = true;
|
||||
}
|
||||
|
@ -253,8 +270,8 @@ void OPENGL_GAL::deleteVertexBufferObjects()
|
|||
glBindBuffer( GL_ARRAY_BUFFER, 0 );
|
||||
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
|
||||
|
||||
glDeleteBuffers( 1, &curVboVertId );
|
||||
glDeleteBuffers( 1, &curVboIndId );
|
||||
glDeleteBuffers( 1, &vboVertices );
|
||||
glDeleteBuffers( 1, &vboIndices );
|
||||
|
||||
isVboInitialized = false;
|
||||
}
|
||||
|
@ -348,7 +365,6 @@ void OPENGL_GAL::BeginDrawing()
|
|||
// Compile the shaders
|
||||
if( !isShaderInitialized && isUseShader )
|
||||
{
|
||||
shader.ConfigureGeometryShader( 3, GL_TRIANGLES, GL_TRIANGLES );
|
||||
shader.AddSource( shaderPath + std::string( "/shader.vert" ), SHADER_TYPE_VERTEX );
|
||||
shader.AddSource( shaderPath + std::string( "/shader.frag" ), SHADER_TYPE_FRAGMENT );
|
||||
if( !shader.Link() )
|
||||
|
@ -417,9 +433,10 @@ void OPENGL_GAL::BeginDrawing()
|
|||
// Number of vertices to be drawn
|
||||
indicesSize = 0;
|
||||
|
||||
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, curVboIndId );
|
||||
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, vboIndices );
|
||||
// Discard old buffer, so we can use it again
|
||||
glBufferData( GL_ELEMENT_ARRAY_BUFFER, vboSize * VBO_ITEM::IndByteSize, NULL, GL_STREAM_DRAW );
|
||||
glBufferData( GL_ELEMENT_ARRAY_BUFFER, vboContainer->GetSize() * VBO_ITEM::IndByteSize,
|
||||
NULL, GL_STREAM_DRAW );
|
||||
|
||||
// Map the GPU memory, so we can store indices that are going to be drawn
|
||||
indicesPtr = static_cast<GLuint*>( glMapBuffer( GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY ) );
|
||||
|
@ -493,7 +510,7 @@ void OPENGL_GAL::EndDrawing()
|
|||
glEnableClientState( GL_COLOR_ARRAY );
|
||||
|
||||
// Bind vertices data buffers
|
||||
glBindBuffer( GL_ARRAY_BUFFER, curVboVertId );
|
||||
glBindBuffer( GL_ARRAY_BUFFER, vboVertices );
|
||||
glVertexPointer( VBO_ITEM::CoordStride, GL_FLOAT, VBO_ITEM::VertByteSize, 0 );
|
||||
glColorPointer( VBO_ITEM::ColorStride, GL_FLOAT, VBO_ITEM::VertByteSize,
|
||||
(GLvoid*) VBO_ITEM::ColorByteOffset );
|
||||
|
@ -544,40 +561,27 @@ void OPENGL_GAL::rebuildVbo()
|
|||
prof_start( &totalTime, false );
|
||||
#endif /* __WXDEBUG__ */
|
||||
|
||||
// Buffer for storing cached items data
|
||||
GLfloat* verticesBuffer = new GLfloat[VBO_ITEM::VertStride * vboSize];
|
||||
GLfloat* data = (GLfloat*) vboContainer->GetAllVertices();
|
||||
|
||||
// Pointer for easier usage with memcpy
|
||||
GLfloat* verticesBufferPtr = verticesBuffer;
|
||||
|
||||
// Fill out buffers with data
|
||||
for( std::deque<VBO_ITEM*>::iterator vboItem = vboItems.begin();
|
||||
vboItem != vboItems.end(); vboItem++ )
|
||||
{
|
||||
int size = (*vboItem)->GetSize();
|
||||
|
||||
memcpy( verticesBufferPtr, (*vboItem)->GetVertices(), size * VBO_ITEM::VertByteSize );
|
||||
verticesBufferPtr += size * VBO_ITEM::VertStride;
|
||||
}
|
||||
|
||||
// Upload vertices coordinates, shader types and indices to GPU memory
|
||||
glBindBuffer( GL_ARRAY_BUFFER, curVboVertId );
|
||||
glBufferData( GL_ARRAY_BUFFER, vboSize * VBO_ITEM::VertByteSize, verticesBuffer, GL_DYNAMIC_DRAW );
|
||||
// Upload vertices coordinates and shader types to GPU memory
|
||||
glBindBuffer( GL_ARRAY_BUFFER, vboVertices );
|
||||
glBufferData( GL_ARRAY_BUFFER, vboContainer->GetSize() * VBO_ITEM::VertByteSize,
|
||||
data, GL_DYNAMIC_DRAW );
|
||||
glBindBuffer( GL_ARRAY_BUFFER, 0 );
|
||||
|
||||
// Allocate the biggest possible buffer for indices
|
||||
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, curVboIndId );
|
||||
glBufferData( GL_ELEMENT_ARRAY_BUFFER, vboSize * VBO_ITEM::IndByteSize, NULL, GL_STREAM_DRAW );
|
||||
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, vboIndices );
|
||||
glBufferData( GL_ELEMENT_ARRAY_BUFFER, vboContainer->GetSize() * VBO_ITEM::IndByteSize,
|
||||
NULL, GL_STREAM_DRAW );
|
||||
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
|
||||
|
||||
delete[] verticesBuffer;
|
||||
vboNeedsUpdate = false;
|
||||
|
||||
#ifdef __WXDEBUG__
|
||||
prof_end( &totalTime );
|
||||
|
||||
wxLogDebug( wxT( "Rebuilding VBO::%d vertices / %.1f ms" ),
|
||||
vboSize, (double) totalTime.value / 1000.0 );
|
||||
vboContainer->GetSize(), (double) totalTime.value / 1000.0 );
|
||||
#endif /* __WXDEBUG__ */
|
||||
}
|
||||
|
||||
|
@ -726,74 +730,6 @@ inline void OPENGL_GAL::drawLineCap( const VECTOR2D& aStartPoint, const VECTOR2D
|
|||
}
|
||||
|
||||
|
||||
void OPENGL_GAL::begin( GLenum aMode )
|
||||
{
|
||||
if( !isGrouping )
|
||||
glBegin( aMode );
|
||||
}
|
||||
|
||||
|
||||
void OPENGL_GAL::end()
|
||||
{
|
||||
if( !isGrouping )
|
||||
glEnd();
|
||||
}
|
||||
|
||||
|
||||
void OPENGL_GAL::vertex3( double aX, double aY, double aZ )
|
||||
{
|
||||
if( isGrouping )
|
||||
{
|
||||
// New vertex coordinates for VBO
|
||||
const GLfloat vertex[] = { aX, aY, aZ };
|
||||
curVboItem->PushVertex( vertex );
|
||||
}
|
||||
else
|
||||
{
|
||||
glVertex3d( aX, aY, aZ );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void OPENGL_GAL::translate3( double aX, double aY, double aZ )
|
||||
{
|
||||
if( isGrouping )
|
||||
{
|
||||
transform = glm::translate( transform, glm::vec3( aX, aY, aZ ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
glTranslated( aX, aY, aZ );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void OPENGL_GAL::color4( double aRed, double aGreen, double aBlue, double aAlpha )
|
||||
{
|
||||
if( isGrouping )
|
||||
{
|
||||
curVboItem->UseColor( COLOR4D( aRed, aGreen, aBlue, aAlpha ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
glColor4d( aRed, aGreen, aBlue, aAlpha );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void OPENGL_GAL::color4( const COLOR4D& aColor )
|
||||
{
|
||||
if( isGrouping )
|
||||
{
|
||||
curVboItem->UseColor( aColor );
|
||||
}
|
||||
else
|
||||
{
|
||||
glColor4d( aColor.r, aColor.g, aColor.b, aColor.a);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void OPENGL_GAL::DrawLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint )
|
||||
{
|
||||
if( isFillEnabled )
|
||||
|
@ -1206,7 +1142,13 @@ void OPENGL_GAL::DrawCircle( const VECTOR2D& aCenterPoint, double aRadius )
|
|||
|
||||
if( isGrouping )
|
||||
{
|
||||
curVboItem->PushVertices( verticesCircle.GetVertices(), verticesCircle.GetSize() );
|
||||
VBO_VERTEX* circle = new VBO_VERTEX[CIRCLE_POINTS * 3];
|
||||
|
||||
memcpy( circle, verticesCircle->GetVertices(),
|
||||
VBO_ITEM::VertByteSize * CIRCLE_POINTS * 3 );
|
||||
curVboItem->PushVertices( circle, CIRCLE_POINTS * 3 );
|
||||
|
||||
delete[] circle;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1256,7 +1198,13 @@ void OPENGL_GAL::drawSemiCircle( const VECTOR2D& aCenterPoint, double aRadius, d
|
|||
|
||||
if( isGrouping )
|
||||
{
|
||||
curVboItem->PushVertices( verticesSemiCircle.GetVertices(), verticesSemiCircle.GetSize() );
|
||||
VBO_VERTEX* semiCircle = new VBO_VERTEX[CIRCLE_POINTS * 3];
|
||||
|
||||
memcpy( semiCircle, verticesSemiCircle->GetVertices(),
|
||||
VBO_ITEM::VertByteSize * CIRCLE_POINTS * 3 );
|
||||
curVboItem->PushVertices( semiCircle, CIRCLE_POINTS * 3 );
|
||||
|
||||
delete[] semiCircle;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1416,32 +1364,19 @@ void OPENGL_GAL::DrawPolygon( const std::deque<VECTOR2D>& aPointList )
|
|||
|
||||
setShader( SHADER_NONE );
|
||||
|
||||
GLUtesselator* tesselator = gluNewTess();
|
||||
|
||||
typedef std::vector<OGLPOINT> OGLPOINTS;
|
||||
|
||||
// Do only one heap allocation, can do because we know size in advance.
|
||||
// std::vector is then fastest
|
||||
OGLPOINTS vertexList( aPointList.size(), OGLPOINT( "fastest" ) );
|
||||
|
||||
InitTesselatorCallbacks( tesselator );
|
||||
|
||||
gluTessProperty( tesselator, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_POSITIVE );
|
||||
|
||||
glNormal3d( 0.0, 0.0, 1.0 );
|
||||
color4( fillColor.r, fillColor.g, fillColor.b, fillColor.a );
|
||||
|
||||
glShadeModel( GL_FLAT );
|
||||
if( isGrouping )
|
||||
{
|
||||
// Store polygon triangles' coordinates to the current VBO item
|
||||
gluTessBeginPolygon( tesselator, curVboItem );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Display polygons directly
|
||||
gluTessBeginPolygon( tesselator, NULL );
|
||||
}
|
||||
|
||||
TessParams params = { curVboItem, tessIntersects };
|
||||
gluTessBeginPolygon( tesselator, ¶ms );
|
||||
gluTessBeginContour( tesselator );
|
||||
|
||||
// use operator=( const POINTS& )
|
||||
|
@ -1456,7 +1391,13 @@ void OPENGL_GAL::DrawPolygon( const std::deque<VECTOR2D>& aPointList )
|
|||
gluTessEndContour( tesselator );
|
||||
gluTessEndPolygon( tesselator );
|
||||
|
||||
gluDeleteTess( tesselator );
|
||||
// Free allocated intersecting points
|
||||
std::vector<GLdouble*>::iterator it, it_end;
|
||||
for( it = tessIntersects.begin(), it_end = tessIntersects.end(); it < it_end; ++it )
|
||||
{
|
||||
delete[] *it;
|
||||
}
|
||||
tessIntersects.clear();
|
||||
|
||||
// vertexList destroyed here
|
||||
}
|
||||
|
@ -1639,8 +1580,7 @@ int OPENGL_GAL::BeginGroup()
|
|||
vboNeedsUpdate = true;
|
||||
|
||||
// Save the pointer for caching the current item
|
||||
curVboItem = new VBO_ITEM;
|
||||
curVboItem->SetOffset( vboSize );
|
||||
curVboItem = new VBO_ITEM( vboContainer );
|
||||
vboItems.push_back( curVboItem );
|
||||
|
||||
return vboItems.size() - 1;
|
||||
|
@ -1649,27 +1589,30 @@ int OPENGL_GAL::BeginGroup()
|
|||
|
||||
void OPENGL_GAL::EndGroup()
|
||||
{
|
||||
vboSize += curVboItem->GetSize();
|
||||
curVboItem->Finish();
|
||||
curVboItem = NULL;
|
||||
isGrouping = false;
|
||||
}
|
||||
|
||||
|
||||
void OPENGL_GAL::ClearCache()
|
||||
{
|
||||
std::deque<VBO_ITEM*>::iterator it, end;
|
||||
for( it = vboItems.begin(), end = vboItems.end(); it != end; it++ )
|
||||
{
|
||||
delete *it;
|
||||
}
|
||||
|
||||
vboItems.clear();
|
||||
}
|
||||
|
||||
|
||||
void OPENGL_GAL::DeleteGroup( int aGroupNumber )
|
||||
{
|
||||
#ifdef __WXDEBUG__
|
||||
if( (unsigned) aGroupNumber < vboItems.size() )
|
||||
{
|
||||
wxLogDebug( wxT( "Tried to delete not existing group" ) );
|
||||
}
|
||||
#endif /* __WXDEBUG__ */
|
||||
VBO_ITEM* item = vboItems[aGroupNumber];
|
||||
|
||||
std::deque<VBO_ITEM*>::iterator it = vboItems.begin();
|
||||
std::advance( it, aGroupNumber );
|
||||
|
||||
// vboSize -= it->GetSize(); // FIXME?
|
||||
delete *it;
|
||||
// vboItems.erase( it ); // makes change to group numbers - that's veeery bad
|
||||
vboItems[aGroupNumber] = NULL;
|
||||
delete item;
|
||||
|
||||
vboNeedsUpdate = true;
|
||||
}
|
||||
|
@ -1687,26 +1630,6 @@ void OPENGL_GAL::DrawGroup( int aGroupNumber )
|
|||
}
|
||||
|
||||
|
||||
// TODO it is not used anywhere
|
||||
/*void OPENGL_GAL::computeUnitArcs()
|
||||
{
|
||||
displayListsArcs = glGenLists( CIRCLE_POINTS + 1 );
|
||||
|
||||
// Create an individual display list for each arc in with an angle [0 .. 2pi]
|
||||
for( int j = 0; j < CIRCLE_POINTS + 1; j++ )
|
||||
{
|
||||
glNewList( displayListsArcs + j, GL_COMPILE );
|
||||
|
||||
for( int i = 0; i < j; i++ )
|
||||
{
|
||||
glVertex2d( cos( 2 * M_PI / CIRCLE_POINTS * i ), sin( 2 * M_PI / CIRCLE_POINTS * i ) );
|
||||
}
|
||||
|
||||
glEndList();
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
void OPENGL_GAL::computeUnitCircle()
|
||||
{
|
||||
displayListCircle = glGenLists( 1 );
|
||||
|
@ -1718,30 +1641,28 @@ void OPENGL_GAL::computeUnitCircle()
|
|||
// Insert in a display list and a vector
|
||||
for( int i = 0; i < CIRCLE_POINTS; i++ )
|
||||
{
|
||||
const GLfloat v0[] = { 0.0f, 0.0f, 0.0f };
|
||||
const GLfloat v1[] =
|
||||
{
|
||||
VBO_VERTEX v0( 0.0f, 0.0f, 0.0f );
|
||||
VBO_VERTEX v1(
|
||||
cos( 2.0 * M_PI / CIRCLE_POINTS * i ), // x
|
||||
sin( 2.0 * M_PI / CIRCLE_POINTS * i ), // y
|
||||
0.0f // z
|
||||
};
|
||||
const GLfloat v2[] =
|
||||
{
|
||||
);
|
||||
VBO_VERTEX v2(
|
||||
cos( 2.0 * M_PI / CIRCLE_POINTS * ( i + 1 ) ), // x
|
||||
sin( 2.0 * M_PI / CIRCLE_POINTS * ( i + 1 ) ), // y
|
||||
0.0f // z
|
||||
};
|
||||
);
|
||||
|
||||
glVertex2d( 0, 0 );
|
||||
verticesCircle.PushVertex( v0 );
|
||||
verticesCircle->PushVertex( &v0 );
|
||||
|
||||
glVertex2d( v1[0], v1[1] );
|
||||
verticesCircle.PushVertex( v1 );
|
||||
unitCirclePoints.push_back( VECTOR2D( v1[0], v1[1] ) ); // TODO remove
|
||||
glVertex2d( v1.x, v1.y );
|
||||
verticesCircle->PushVertex( &v1 );
|
||||
unitCirclePoints.push_back( VECTOR2D( v1.x, v1.y ) ); // TODO remove
|
||||
|
||||
glVertex2d( v2[0], v2[1] );
|
||||
verticesCircle.PushVertex( v2 );
|
||||
unitCirclePoints.push_back( VECTOR2D( v2[0], v2[1] ) ); // TODO remove
|
||||
glVertex2d( v2.x, v2.y );
|
||||
verticesCircle->PushVertex( &v2 );
|
||||
unitCirclePoints.push_back( VECTOR2D( v2.x, v2.y ) ); // TODO remove
|
||||
}
|
||||
|
||||
glEnd();
|
||||
|
@ -1759,28 +1680,26 @@ void OPENGL_GAL::computeUnitSemiCircle()
|
|||
|
||||
for( int i = 0; i < CIRCLE_POINTS / 2; ++i )
|
||||
{
|
||||
GLfloat v0[] = { 0.0f, 0.0f, 0.0f };
|
||||
GLfloat v1[] =
|
||||
{
|
||||
VBO_VERTEX v0( 0.0f, 0.0f, 0.0f );
|
||||
VBO_VERTEX v1(
|
||||
cos( 2.0 * M_PI / CIRCLE_POINTS * i ), // x
|
||||
sin( 2.0 * M_PI / CIRCLE_POINTS * i ), // y
|
||||
0.0f // z
|
||||
};
|
||||
GLfloat v2[] =
|
||||
{
|
||||
);
|
||||
VBO_VERTEX v2(
|
||||
cos( 2.0 * M_PI / CIRCLE_POINTS * ( i + 1 ) ), // x
|
||||
sin( 2.0 * M_PI / CIRCLE_POINTS * ( i + 1 ) ), // y
|
||||
0.0f // z
|
||||
};
|
||||
);
|
||||
|
||||
glVertex2d( 0, 0 );
|
||||
verticesSemiCircle.PushVertex( v0 );
|
||||
verticesSemiCircle->PushVertex( &v0 );
|
||||
|
||||
glVertex2d( v1[0], v1[1] );
|
||||
verticesSemiCircle.PushVertex( v1 );
|
||||
glVertex2d( v1.x, v1.y );
|
||||
verticesSemiCircle->PushVertex( &v1 );
|
||||
|
||||
glVertex2d( v2[0], v2[1] );
|
||||
verticesSemiCircle.PushVertex( v2 );
|
||||
glVertex2d( v2.x, v2.y );
|
||||
verticesSemiCircle->PushVertex( &v2 );
|
||||
}
|
||||
|
||||
glEnd();
|
||||
|
@ -1825,12 +1744,13 @@ void OPENGL_GAL::ComputeWorldScreenMatrix()
|
|||
void CALLBACK VertexCallback( GLvoid* aVertexPtr, void* aData )
|
||||
{
|
||||
GLdouble* vertex = static_cast<GLdouble*>( aVertexPtr );
|
||||
OPENGL_GAL::TessParams* param = static_cast<OPENGL_GAL::TessParams*>( aData );
|
||||
VBO_ITEM* vboItem = param->vboItem;
|
||||
|
||||
if( aData )
|
||||
if( vboItem )
|
||||
{
|
||||
VBO_ITEM* vboItem = static_cast<VBO_ITEM*>( aData );
|
||||
const GLfloat newVertex[] = { vertex[0], vertex[1], vertex[2] };
|
||||
vboItem->PushVertex( newVertex );
|
||||
VBO_VERTEX newVertex( vertex[0], vertex[1], vertex[2] );
|
||||
vboItem->PushVertex( &newVertex );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1841,9 +1761,13 @@ void CALLBACK VertexCallback( GLvoid* aVertexPtr, void* aData )
|
|||
|
||||
void CALLBACK CombineCallback( GLdouble coords[3],
|
||||
GLdouble* vertex_data[4],
|
||||
GLfloat weight[4], GLdouble** dataOut )
|
||||
GLfloat weight[4], GLdouble** dataOut, void* aData )
|
||||
{
|
||||
GLdouble* vertex = new GLdouble[3];
|
||||
OPENGL_GAL::TessParams* param = static_cast<OPENGL_GAL::TessParams*>( aData );
|
||||
|
||||
// Save the pointer so we can delete it later
|
||||
param->intersectPoints.push_back( vertex );
|
||||
|
||||
memcpy( vertex, coords, 3 * sizeof(GLdouble) );
|
||||
|
||||
|
@ -1884,7 +1808,7 @@ void CALLBACK ErrorCallback( GLenum aErrorCode )
|
|||
void InitTesselatorCallbacks( GLUtesselator* aTesselator )
|
||||
{
|
||||
gluTessCallback( aTesselator, GLU_TESS_VERTEX_DATA, ( void (CALLBACK*)() )VertexCallback );
|
||||
gluTessCallback( aTesselator, GLU_TESS_COMBINE, ( void (CALLBACK*)() )CombineCallback );
|
||||
gluTessCallback( aTesselator, GLU_TESS_COMBINE_DATA, ( void (CALLBACK*)() )CombineCallback );
|
||||
gluTessCallback( aTesselator, GLU_TESS_EDGE_FLAG, ( void (CALLBACK*)() )EdgeCallback );
|
||||
gluTessCallback( aTesselator, GLU_TESS_BEGIN_DATA, ( void (CALLBACK*)() )BeginCallback );
|
||||
gluTessCallback( aTesselator, GLU_TESS_END_DATA, ( void (CALLBACK*)() )EndCallback );
|
||||
|
|
|
@ -0,0 +1,369 @@
|
|||
/*
|
||||
* 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 vbo_container.cpp
|
||||
* @brief Class to store VBO_ITEMs.
|
||||
*/
|
||||
|
||||
#include <gal/opengl/vbo_container.h>
|
||||
#include <gal/opengl/vbo_item.h>
|
||||
#include <cstring>
|
||||
#include <wx/log.h>
|
||||
#ifdef __WXDEBUG__
|
||||
#include <profile.h>
|
||||
#endif /* __WXDEBUG__ */
|
||||
|
||||
#define CONTAINER_TEST 1
|
||||
|
||||
using namespace KiGfx;
|
||||
|
||||
VBO_CONTAINER::VBO_CONTAINER( int aSize ) :
|
||||
m_freeSpace( aSize ), m_currentSize( aSize ), itemStarted( false )
|
||||
{
|
||||
m_vertices = new VBO_VERTEX[aSize];
|
||||
|
||||
// In the beginning there is only free space
|
||||
m_freeChunks.insert( Chunk( aSize, 0 ) );
|
||||
}
|
||||
|
||||
|
||||
VBO_CONTAINER::~VBO_CONTAINER()
|
||||
{
|
||||
delete[] m_vertices;
|
||||
}
|
||||
|
||||
|
||||
void VBO_CONTAINER::StartItem( VBO_ITEM* aVboItem )
|
||||
{
|
||||
itemStarted = true;
|
||||
item = aVboItem;
|
||||
itemSize = 0;
|
||||
|
||||
// Reserve minimal sensible chunk size (at least to store a single triangle)
|
||||
itemChunkSize = 3;
|
||||
allocate( aVboItem, itemChunkSize );
|
||||
}
|
||||
|
||||
|
||||
void VBO_CONTAINER::EndItem()
|
||||
{
|
||||
if( itemSize < itemChunkSize )
|
||||
{
|
||||
// There is some memory left, so we should return it to the pool
|
||||
int itemChunkOffset = item->GetOffset();
|
||||
|
||||
m_reservedChunks.erase( item );
|
||||
m_reservedChunks.insert( ReservedChunk( item, Chunk( itemSize, itemChunkOffset ) ) );
|
||||
|
||||
m_freeChunks.insert( Chunk( itemChunkSize - itemSize, itemChunkOffset + itemSize ) );
|
||||
m_freeSpace += ( itemChunkSize - itemSize );
|
||||
}
|
||||
|
||||
itemStarted = false;
|
||||
}
|
||||
|
||||
|
||||
void VBO_CONTAINER::Add( VBO_ITEM* aVboItem, const VBO_VERTEX* aVertex, unsigned int aSize )
|
||||
{
|
||||
unsigned int offset;
|
||||
|
||||
if( itemStarted ) // There is an item being created with an unknown size..
|
||||
{
|
||||
unsigned int itemChunkOffset;
|
||||
|
||||
// ..and unfortunately does not fit into currently reserved chunk
|
||||
if( itemSize + aSize > itemChunkSize )
|
||||
{
|
||||
// Find the previous chunk for the item, save it, so it can be removed later
|
||||
ReservedChunkMap::iterator it = m_reservedChunks.find( item );
|
||||
|
||||
// Reserve bigger memory for the current item
|
||||
int newSize = ( 2 * itemSize ) + aSize;
|
||||
itemChunkOffset = allocate( aVboItem, newSize );
|
||||
|
||||
// Check if there was no error
|
||||
if( itemChunkOffset > m_currentSize )
|
||||
return;
|
||||
|
||||
// Save previous chunk's offset for copying data
|
||||
int oldItemChunkOffset = getChunkOffset( *it );
|
||||
|
||||
// Copy all the old data
|
||||
memcpy( &m_vertices[itemChunkOffset], &m_vertices[oldItemChunkOffset],
|
||||
itemSize * VBO_ITEM::VertByteSize );
|
||||
|
||||
// Return memory used by the previous chunk
|
||||
free( it );
|
||||
|
||||
itemChunkSize = newSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
itemChunkOffset = item->GetOffset();
|
||||
}
|
||||
|
||||
// Store new vertices in the chunk reserved for the unknown-sized item
|
||||
offset = itemChunkOffset + itemSize;
|
||||
itemSize += aSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Add vertices to previously already finished item
|
||||
wxASSERT_MSG( false, wxT( "Warning: not tested yet" ) );
|
||||
|
||||
ReservedChunkMap::iterator it = m_reservedChunks.find( aVboItem );
|
||||
unsigned int chunkSize = getChunkSize( *it );
|
||||
unsigned int itemSize = aVboItem->GetSize();
|
||||
|
||||
if( chunkSize < itemSize + aSize )
|
||||
{
|
||||
resizeChunk( aVboItem, itemSize + aSize );
|
||||
it = m_reservedChunks.find( aVboItem );
|
||||
}
|
||||
|
||||
offset = getChunkOffset( *it ) + itemSize;
|
||||
}
|
||||
|
||||
memcpy( &m_vertices[offset], aVertex, aSize * VBO_ITEM::VertByteSize );
|
||||
}
|
||||
|
||||
|
||||
VBO_VERTEX* VBO_CONTAINER::GetAllVertices() const
|
||||
{
|
||||
return m_vertices;
|
||||
}
|
||||
|
||||
|
||||
VBO_VERTEX* VBO_CONTAINER::GetVertices( const VBO_ITEM* aVboItem ) const
|
||||
{
|
||||
int offset = aVboItem->GetOffset();
|
||||
|
||||
return &m_vertices[offset];
|
||||
}
|
||||
|
||||
|
||||
unsigned int VBO_CONTAINER::allocate( VBO_ITEM* aVboItem, unsigned int aSize )
|
||||
{
|
||||
// Is there enough space to store vertices?
|
||||
if( m_freeSpace < aSize )
|
||||
{
|
||||
bool result;
|
||||
|
||||
// Would it be enough to double the current space?
|
||||
if( aSize < m_freeSpace + m_currentSize )
|
||||
{
|
||||
// Yes: exponential growing
|
||||
result = resizeContainer( m_currentSize * 2 );
|
||||
}
|
||||
else
|
||||
{
|
||||
// No: grow to the nearest bigger power of 2
|
||||
result = resizeContainer( getPowerOf2( m_currentSize * 2 + aSize ) );
|
||||
}
|
||||
|
||||
// An error has occurred
|
||||
if( !result )
|
||||
return UINT_MAX;
|
||||
}
|
||||
|
||||
// Look for the space with at least given size
|
||||
FreeChunkMap::iterator it = m_freeChunks.lower_bound( aSize );
|
||||
|
||||
if( it == m_freeChunks.end() )
|
||||
{
|
||||
// This means that there is enough space for
|
||||
// storing vertices, but the space is not continous
|
||||
if( !defragment() )
|
||||
return false;
|
||||
|
||||
// We can take the first free chunk, as there is only one after defragmentation
|
||||
// and we can be sure that it provides enough space to store the object
|
||||
it = m_freeChunks.begin();
|
||||
}
|
||||
|
||||
unsigned int chunkSize = it->first;
|
||||
unsigned int chunkOffset = it->second;
|
||||
m_freeChunks.erase( it );
|
||||
|
||||
wxASSERT( chunkSize >= aSize );
|
||||
|
||||
// If there is some space left, return it to the pool - add an entry for it
|
||||
if( chunkSize > aSize )
|
||||
{
|
||||
m_freeChunks.insert( Chunk( chunkSize - aSize, chunkOffset + aSize ) );
|
||||
}
|
||||
m_freeSpace -= aSize;
|
||||
m_reservedChunks.insert( ReservedChunk( aVboItem, Chunk( aSize, chunkOffset ) ) );
|
||||
|
||||
aVboItem->SetOffset( chunkOffset );
|
||||
|
||||
return chunkOffset;
|
||||
}
|
||||
|
||||
|
||||
void VBO_CONTAINER::free( const ReservedChunkMap::iterator& aChunk )
|
||||
{
|
||||
// Remove the chunk from the reserved chunks map and add to the free chunks map
|
||||
int size = getChunkSize( *aChunk );
|
||||
int offset = getChunkOffset( *aChunk );
|
||||
|
||||
m_reservedChunks.erase( aChunk );
|
||||
m_freeChunks.insert( Chunk( size, offset ) );
|
||||
m_freeSpace += size;
|
||||
}
|
||||
|
||||
|
||||
bool VBO_CONTAINER::defragment( VBO_VERTEX* aTarget )
|
||||
{
|
||||
if( m_freeChunks.size() <= 1 )
|
||||
{
|
||||
// There is no point in defragmenting, as there is only one or no free chunks
|
||||
return true;
|
||||
}
|
||||
|
||||
if( aTarget == NULL )
|
||||
{
|
||||
// No target was specified, so we have to allocate our own space
|
||||
aTarget = new (std::nothrow) VBO_VERTEX[m_currentSize];
|
||||
if( aTarget == NULL )
|
||||
{
|
||||
wxLogError( wxT( "Run out of memory" ) );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int newOffset = 0;
|
||||
ReservedChunkMap::iterator it, it_end;
|
||||
for( it = m_reservedChunks.begin(), it_end = m_reservedChunks.end(); it != it_end; ++it )
|
||||
{
|
||||
VBO_ITEM* vboItem = getChunkVboItem( *it );
|
||||
int itemOffset = getChunkOffset( *it );
|
||||
int itemSize = getChunkSize( *it );
|
||||
|
||||
// Move an item to the new container
|
||||
memcpy( &aTarget[newOffset], &m_vertices[itemOffset], itemSize * VBO_ITEM::VertByteSize );
|
||||
|
||||
// Update new offset
|
||||
vboItem->SetOffset( newOffset );
|
||||
setChunkOffset( *it, newOffset );
|
||||
|
||||
// Move to the next free space
|
||||
newOffset += itemSize;
|
||||
}
|
||||
|
||||
delete[] m_vertices;
|
||||
m_vertices = aTarget;
|
||||
|
||||
// Now there is only one big chunk of free memory
|
||||
m_freeChunks.clear();
|
||||
m_freeChunks.insert( Chunk( m_freeSpace, m_currentSize - m_freeSpace ) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void VBO_CONTAINER::resizeChunk( VBO_ITEM* aVboItem, int aNewSize )
|
||||
{
|
||||
wxASSERT_MSG( false, wxT( "Warning: not tested yet" ) );
|
||||
|
||||
// TODO ESPECIALLY test the case of shrinking chunk
|
||||
ReservedChunkMap::iterator it = m_reservedChunks.find( aVboItem );
|
||||
int size = getChunkSize( *it );
|
||||
int offset = getChunkOffset( *it );
|
||||
|
||||
int newOffset = allocate( aVboItem, aNewSize );
|
||||
memcpy( &m_vertices[newOffset], &m_vertices[offset], size * VBO_ITEM::VertByteSize );
|
||||
|
||||
// Remove the chunk from the reserved chunks map and add to the free chunks map
|
||||
m_reservedChunks.erase( it );
|
||||
m_freeChunks.insert( Chunk( size, offset ) );
|
||||
m_freeSpace += size;
|
||||
}
|
||||
|
||||
|
||||
bool VBO_CONTAINER::resizeContainer( unsigned int aNewSize )
|
||||
{
|
||||
unsigned int copySize;
|
||||
if( aNewSize < m_currentSize )
|
||||
{
|
||||
// Sanity check, no shrinking if we cannot fit all the data
|
||||
if( ( m_currentSize - m_freeSpace ) > aNewSize )
|
||||
return false;
|
||||
|
||||
defragment();
|
||||
copySize = ( m_currentSize - m_freeSpace );
|
||||
}
|
||||
else
|
||||
{
|
||||
copySize = m_currentSize;
|
||||
}
|
||||
|
||||
VBO_VERTEX* newContainer = new (std::nothrow) VBO_VERTEX[aNewSize];
|
||||
if( newContainer == NULL )
|
||||
{
|
||||
wxLogError( wxT( "Run out of memory" ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy( newContainer, m_vertices, copySize * VBO_ITEM::VertByteSize );
|
||||
delete[] m_vertices;
|
||||
m_vertices = newContainer;
|
||||
|
||||
// Update variables
|
||||
unsigned int lastFreeSize = 0;
|
||||
unsigned int lastFreeOffset = 0;
|
||||
|
||||
// Search for the last free chunk *at the end of the container* (not the last chunk in general)
|
||||
FreeChunkMap::reverse_iterator lastFree, freeEnd;
|
||||
for( lastFree = m_freeChunks.rbegin(), freeEnd = m_freeChunks.rend();
|
||||
lastFree != freeEnd && lastFreeSize + lastFreeOffset != m_currentSize; ++lastFree )
|
||||
{
|
||||
lastFreeSize = getChunkSize( *lastFree );
|
||||
lastFreeOffset = getChunkOffset( *lastFree );
|
||||
}
|
||||
|
||||
if( lastFreeSize + lastFreeOffset == m_currentSize )
|
||||
{
|
||||
// We found a chunk at the end of the container
|
||||
m_freeChunks.erase( lastFree.base() );
|
||||
// so we can merge it with the new free chunk
|
||||
m_freeChunks.insert( Chunk( aNewSize - m_currentSize + lastFreeSize, // size
|
||||
m_currentSize - lastFreeSize ) ); // offset
|
||||
}
|
||||
else
|
||||
{
|
||||
// As there is no free chunk at the end of container - simply add a new entry
|
||||
if( aNewSize > m_currentSize ) // only in the case of enlargement
|
||||
{
|
||||
m_freeChunks.insert( Chunk( aNewSize - m_currentSize, // size
|
||||
m_currentSize ) ); // offset
|
||||
}
|
||||
}
|
||||
|
||||
m_freeSpace += ( aNewSize - m_currentSize );
|
||||
m_currentSize = aNewSize;
|
||||
|
||||
return true;
|
||||
}
|
|
@ -27,107 +27,98 @@
|
|||
* @brief Class to handle an item held in a Vertex Buffer Object.
|
||||
*/
|
||||
|
||||
#include <gal/opengl/vbo_container.h>
|
||||
#include <gal/opengl/vbo_item.h>
|
||||
#include <cstring>
|
||||
|
||||
using namespace KiGfx;
|
||||
|
||||
VBO_ITEM::VBO_ITEM() :
|
||||
m_vertices( NULL ),
|
||||
VBO_ITEM::VBO_ITEM( VBO_CONTAINER* aContainer ) :
|
||||
m_offset( 0 ),
|
||||
m_size( 0 ),
|
||||
m_container( aContainer ),
|
||||
m_isDirty( true ),
|
||||
m_transform( NULL )
|
||||
{
|
||||
// By default no shader is used
|
||||
m_shader[0] = 0;
|
||||
|
||||
// Prepare a block for storing vertices & indices
|
||||
useNewBlock();
|
||||
// The item's size is not known yet, so we just start an item in the container
|
||||
aContainer->StartItem( this );
|
||||
}
|
||||
|
||||
|
||||
VBO_ITEM::~VBO_ITEM()
|
||||
{
|
||||
if( m_isDirty )
|
||||
{
|
||||
// Data is still stored in blocks
|
||||
std::list<VBO_VERTEX*>::const_iterator v_it, v_end;
|
||||
for( v_it = m_vertBlocks.begin(), v_end = m_vertBlocks.end(); v_it != v_end; ++v_it )
|
||||
delete[] *v_it;
|
||||
}
|
||||
|
||||
if( m_vertices )
|
||||
delete m_vertices;
|
||||
m_container->Free( this );
|
||||
}
|
||||
|
||||
|
||||
void VBO_ITEM::PushVertex( const GLfloat* aVertex )
|
||||
void VBO_ITEM::PushVertex( VBO_VERTEX* aVertex )
|
||||
{
|
||||
if( m_spaceLeft == 0 )
|
||||
useNewBlock();
|
||||
|
||||
if( m_transform != NULL )
|
||||
{
|
||||
// Apply transformations
|
||||
// X, Y, Z coordinates
|
||||
glm::vec4 vertex( aVertex[0], aVertex[1], aVertex[2], 1.0f );
|
||||
glm::vec4 vertex( aVertex->x, aVertex->y, aVertex->z, 1.0f );
|
||||
vertex = *m_transform * vertex;
|
||||
|
||||
// Replace only coordinates, leave color as it is
|
||||
memcpy( &m_vertPtr->x, &vertex[0], CoordByteSize );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Add the new vertex
|
||||
memcpy( &m_vertPtr->x, aVertex, CoordByteSize );
|
||||
aVertex->x = vertex.x;
|
||||
aVertex->y = vertex.y;
|
||||
aVertex->z = vertex.z;
|
||||
}
|
||||
|
||||
// Apply currently used color
|
||||
memcpy( &m_vertPtr->r, m_color, ColorByteSize );
|
||||
aVertex->r = m_color[0];
|
||||
aVertex->g = m_color[1];
|
||||
aVertex->b = m_color[2];
|
||||
aVertex->a = m_color[3];
|
||||
|
||||
// Apply currently used shader
|
||||
memcpy( &m_vertPtr->shader, m_shader, ShaderByteSize );
|
||||
for( int i = 0; i < ShaderStride; ++i )
|
||||
{
|
||||
aVertex->shader[i] = m_shader[i];
|
||||
}
|
||||
|
||||
// Move to the next free space
|
||||
m_vertPtr++;
|
||||
m_container->Add( this, aVertex );
|
||||
|
||||
m_size++;
|
||||
m_isDirty = true;
|
||||
m_spaceLeft--;
|
||||
}
|
||||
|
||||
|
||||
void VBO_ITEM::PushVertices( const GLfloat* aVertices, GLuint aSize )
|
||||
void VBO_ITEM::PushVertices( VBO_VERTEX* aVertices, GLuint aSize )
|
||||
{
|
||||
for( unsigned int i = 0; i < aSize; ++i )
|
||||
{
|
||||
PushVertex( &aVertices[i * VertStride] );
|
||||
PushVertex( &aVertices[i] );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
GLfloat* VBO_ITEM::GetVertices()
|
||||
VBO_VERTEX* VBO_ITEM::GetVertices()
|
||||
{
|
||||
if( m_isDirty )
|
||||
prepareFinal();
|
||||
Finish();
|
||||
|
||||
return m_vertices;
|
||||
return m_container->GetVertices( this );
|
||||
}
|
||||
|
||||
|
||||
void VBO_ITEM::ChangeColor( const COLOR4D& aColor )
|
||||
{
|
||||
wxASSERT_MSG( false, wxT( "This was not tested yet" ) );
|
||||
|
||||
if( m_isDirty )
|
||||
prepareFinal();
|
||||
Finish();
|
||||
|
||||
// Point to color of vertices
|
||||
GLfloat* vertexPtr = m_vertices + ColorOffset;
|
||||
VBO_VERTEX* vertexPtr = GetVertices();
|
||||
const GLfloat newColor[] = { aColor.r, aColor.g, aColor.b, aColor.a };
|
||||
|
||||
for( int i = 0; i < m_size; ++i )
|
||||
for( unsigned int i = 0; i < m_size; ++i )
|
||||
{
|
||||
memcpy( vertexPtr, newColor, ColorByteSize );
|
||||
memcpy( &vertexPtr->r, newColor, ColorByteSize );
|
||||
|
||||
// Move on to the next vertex
|
||||
vertexPtr++;
|
||||
|
@ -135,38 +126,10 @@ void VBO_ITEM::ChangeColor( const COLOR4D& aColor )
|
|||
}
|
||||
|
||||
|
||||
void VBO_ITEM::useNewBlock()
|
||||
void VBO_ITEM::Finish()
|
||||
{
|
||||
VBO_VERTEX* newVertBlock = new VBO_VERTEX[BLOCK_SIZE];
|
||||
|
||||
m_vertPtr = newVertBlock;
|
||||
m_vertBlocks.push_back( newVertBlock );
|
||||
|
||||
m_spaceLeft = BLOCK_SIZE;
|
||||
}
|
||||
|
||||
|
||||
void VBO_ITEM::prepareFinal()
|
||||
{
|
||||
if( m_vertices )
|
||||
delete m_vertices;
|
||||
|
||||
// Allocate memory that would store all of vertices
|
||||
m_vertices = new GLfloat[m_size * VertStride];
|
||||
// Set the pointer that will move along the buffer
|
||||
GLfloat* vertPtr = m_vertices;
|
||||
|
||||
// Copy blocks of vertices one after another to m_vertices
|
||||
std::list<VBO_VERTEX*>::const_iterator v_it;
|
||||
for( v_it = m_vertBlocks.begin(); *v_it != m_vertBlocks.back(); ++v_it )
|
||||
{
|
||||
memcpy( vertPtr, *v_it, BLOCK_SIZE * VertByteSize );
|
||||
delete[] *v_it;
|
||||
vertPtr += ( BLOCK_SIZE * VertStride );
|
||||
}
|
||||
|
||||
// In the last block we need to copy only used vertices
|
||||
memcpy( vertPtr, *v_it, ( BLOCK_SIZE - m_spaceLeft ) * VertByteSize );
|
||||
// The unknown-sized item has just ended, so we need to inform the container about it
|
||||
m_container->EndItem();
|
||||
|
||||
m_isDirty = false;
|
||||
}
|
||||
|
|
|
@ -66,8 +66,8 @@ bool STROKE_FONT::LoadNewStrokeFont( const char* const aNewStrokeFont[], int aNe
|
|||
|
||||
while( aNewStrokeFont[j][i] )
|
||||
{
|
||||
VECTOR2D point;
|
||||
char coordinate[2];
|
||||
VECTOR2D point( 0.0, 0.0 );
|
||||
char coordinate[2] = { 0, };
|
||||
|
||||
for( int k = 0; k < 2; k++ )
|
||||
{
|
||||
|
|
|
@ -79,6 +79,7 @@ PAINTER::PAINTER( GAL* aGal ) :
|
|||
PAINTER::~PAINTER()
|
||||
{
|
||||
delete m_stroke_font;
|
||||
delete m_settings;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -473,6 +473,11 @@ void VIEW::Clear()
|
|||
|
||||
l->items->RemoveAll();
|
||||
}
|
||||
|
||||
if( m_useGroups )
|
||||
{
|
||||
m_gal->ClearCache();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -111,7 +111,7 @@ void VIEW_ITEM::setGroup( int aLayer, int aId )
|
|||
if( m_groupsSize > 0 )
|
||||
{
|
||||
std::copy( m_groups, m_groups + m_groupsSize, newGroups );
|
||||
delete m_groups;
|
||||
delete[] m_groups;
|
||||
}
|
||||
|
||||
m_groups = newGroups;
|
||||
|
@ -123,7 +123,7 @@ void VIEW_ITEM::deleteGroups()
|
|||
{
|
||||
if( m_groupsSize > 0 )
|
||||
{
|
||||
delete m_groups;
|
||||
delete[] m_groups;
|
||||
m_groupsSize = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -212,6 +212,9 @@ public:
|
|||
/// @copydoc GAL::DeleteGroup()
|
||||
virtual void DeleteGroup( int aGroupNumber );
|
||||
|
||||
/// @copydoc GAL::ClearCache()
|
||||
virtual void ClearCache();
|
||||
|
||||
// --------------------------------------------------------
|
||||
// Handling the world <-> screen transformation
|
||||
// --------------------------------------------------------
|
||||
|
|
|
@ -370,6 +370,11 @@ public:
|
|||
*/
|
||||
virtual void DeleteGroup( int aGroupNumber ) = 0;
|
||||
|
||||
/**
|
||||
* @brief Delete all data created during caching of graphic items.
|
||||
*/
|
||||
virtual void ClearCache() = 0;
|
||||
|
||||
// --------------------------------------------------------
|
||||
// Handling the world <-> screen transformation
|
||||
// --------------------------------------------------------
|
||||
|
|
|
@ -35,6 +35,8 @@
|
|||
|
||||
// OpenGL mathematics library
|
||||
#define GLM_FORCE_RADIANS
|
||||
#include <gal/opengl/glm/gtc/matrix_transform.hpp>
|
||||
|
||||
#include <gal/opengl/vbo_item.h>
|
||||
#include <gal/opengl/shader.h>
|
||||
|
||||
|
@ -56,7 +58,7 @@
|
|||
namespace KiGfx
|
||||
{
|
||||
class SHADER;
|
||||
class VBO_ITEM;
|
||||
class VBO_CONTAINER;
|
||||
|
||||
/**
|
||||
* @brief Class OpenGL_GAL is the OpenGL implementation of the Graphics Abstraction Layer.
|
||||
|
@ -236,6 +238,9 @@ public:
|
|||
/// @copydoc GAL::DeleteGroup()
|
||||
virtual void DeleteGroup( int aGroupNumber );
|
||||
|
||||
/// @copydoc GAL::ClearCache()
|
||||
virtual void ClearCache();
|
||||
|
||||
// --------------------------------------------------------
|
||||
// Handling the world <-> screen transformation
|
||||
// --------------------------------------------------------
|
||||
|
@ -315,6 +320,13 @@ public:
|
|||
shaderPath = aPath;
|
||||
}
|
||||
|
||||
///< Parameters passed to the GLU tesselator
|
||||
typedef struct
|
||||
{
|
||||
VBO_ITEM* vboItem; ///< VBO_ITEM for storing new vertices
|
||||
std::vector<GLdouble*>& intersectPoints; ///< Intersect points, that have to be freed
|
||||
} TessParams;
|
||||
|
||||
protected:
|
||||
virtual void DrawGridLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint );
|
||||
|
||||
|
@ -336,20 +348,19 @@ private:
|
|||
wxEvtHandler* mouseListener;
|
||||
wxEvtHandler* paintListener;
|
||||
|
||||
// Display lists
|
||||
GLuint displayListsArcs; ///< Arc display list
|
||||
VBO_ITEM verticesArc;
|
||||
// Display lists (used in shaderless mode)
|
||||
VBO_CONTAINER* precomputedContainer; ///< Container for storing display lists
|
||||
GLuint displayListCircle; ///< Circle display list
|
||||
VBO_ITEM verticesCircle;
|
||||
VBO_ITEM* verticesCircle;
|
||||
GLuint displayListSemiCircle; ///< Semi circle display list
|
||||
VBO_ITEM verticesSemiCircle;
|
||||
VBO_ITEM* verticesSemiCircle;
|
||||
|
||||
// Vertex buffer objects related fields
|
||||
std::deque<VBO_ITEM*> vboItems; ///< Stores informations about VBO objects
|
||||
VBO_ITEM* curVboItem; ///< Currently used VBO_ITEM (for grouping)
|
||||
GLuint curVboVertId; ///< Currently used vertices VBO handle
|
||||
GLuint curVboIndId; ///< Currently used indices VBO handle
|
||||
int vboSize; ///< Amount of vertices stored in VBO
|
||||
VBO_CONTAINER* vboContainer; ///< Container for storing VBO_ITEMs
|
||||
GLuint vboVertices; ///< Currently used vertices VBO handle
|
||||
GLuint vboIndices; ///< Currently used indices VBO handle
|
||||
bool vboNeedsUpdate; ///< Flag indicating if VBO should be rebuilt
|
||||
glm::mat4 transform; ///< Current transformation matrix
|
||||
std::stack<glm::mat4> transformStack; ///< Stack of transformation matrices
|
||||
|
@ -361,7 +372,8 @@ private:
|
|||
std::deque<VECTOR2D> unitCirclePoints; ///< List of the points on a unit circle
|
||||
|
||||
// Polygon tesselation
|
||||
GLUtesselator* tesselator; ///< Pointer to the tesselator
|
||||
GLUtesselator* tesselator; ///< Pointer to the tesselator
|
||||
std::vector<GLdouble*> tessIntersects; ///< Storage of intersecting points
|
||||
|
||||
// Shader
|
||||
// Possible types of shaders
|
||||
|
@ -519,12 +531,20 @@ private:
|
|||
* @brief Starts drawing in immediate mode or does nothing if an item's caching has started.
|
||||
* @param aMode specifies the primitive or primitives that will be created.
|
||||
*/
|
||||
inline void begin( GLenum aMode );
|
||||
inline void begin( GLenum aMode )
|
||||
{
|
||||
if( !isGrouping )
|
||||
glBegin( aMode );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Ends drawing in immediate mode or does nothing if an item's caching has started.
|
||||
*/
|
||||
inline void end();
|
||||
inline void end()
|
||||
{
|
||||
if( !isGrouping )
|
||||
glEnd();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Adds vertex to the current item or draws it in immediate mode.
|
||||
|
@ -532,7 +552,19 @@ private:
|
|||
* @param aY is Y coordinate.
|
||||
* @param aZ is Z coordinate.
|
||||
*/
|
||||
inline void vertex3( double aX, double aY, double aZ );
|
||||
inline void vertex3( double aX, double aY, double aZ )
|
||||
{
|
||||
if( isGrouping )
|
||||
{
|
||||
// New vertex coordinates for VBO
|
||||
VBO_VERTEX vertex( aX, aY, aZ );
|
||||
curVboItem->PushVertex( &vertex );
|
||||
}
|
||||
else
|
||||
{
|
||||
glVertex3d( aX, aY, aZ );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function that replaces glTranslate and behaves according to isGrouping variable.
|
||||
|
@ -543,7 +575,17 @@ private:
|
|||
* @param aY is translation in Y axis direction.
|
||||
* @param aZ is translation in Z axis direction.
|
||||
*/
|
||||
inline void translate3( double aX, double aY, double aZ );
|
||||
inline void translate3( double aX, double aY, double aZ )
|
||||
{
|
||||
if( isGrouping )
|
||||
{
|
||||
transform = glm::translate( transform, glm::vec3( aX, aY, aZ ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
glTranslated( aX, aY, aZ );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function that replaces glColor and behaves according to isGrouping variable.
|
||||
|
@ -555,7 +597,17 @@ private:
|
|||
* @param aB is blue component.
|
||||
* @param aA is alpha component.
|
||||
*/
|
||||
inline void color4( double aRed, double aGreen, double aBlue, double aAlpha );
|
||||
inline void color4( double aRed, double aGreen, double aBlue, double aAlpha )
|
||||
{
|
||||
if( isGrouping )
|
||||
{
|
||||
curVboItem->UseColor( COLOR4D( aRed, aGreen, aBlue, aAlpha ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
glColor4d( aRed, aGreen, aBlue, aAlpha );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function that replaces glColor and behaves according to isGrouping variable.
|
||||
|
@ -564,7 +616,17 @@ private:
|
|||
*
|
||||
* @param aColor is the new color.
|
||||
*/
|
||||
inline void color4( const COLOR4D& aColor );
|
||||
inline void color4( const COLOR4D& aColor )
|
||||
{
|
||||
if( isGrouping )
|
||||
{
|
||||
curVboItem->UseColor( aColor );
|
||||
}
|
||||
else
|
||||
{
|
||||
glColor4d( aColor.r, aColor.g, aColor.b, aColor.a);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function that sets shader and its parameters for the currently used VBO_ITEM.
|
||||
|
|
|
@ -0,0 +1,256 @@
|
|||
/*
|
||||
* 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 vbo_container.h
|
||||
* @brief Class to store VBO_ITEMs.
|
||||
*/
|
||||
|
||||
#ifndef VBO_CONTAINER_H_
|
||||
#define VBO_CONTAINER_H_
|
||||
|
||||
#include <GL/gl.h>
|
||||
#include <map>
|
||||
#include <wx/log.h>
|
||||
|
||||
namespace KiGfx
|
||||
{
|
||||
class VBO_ITEM;
|
||||
typedef struct VBO_VERTEX VBO_VERTEX;
|
||||
|
||||
class VBO_CONTAINER
|
||||
{
|
||||
public:
|
||||
VBO_CONTAINER( int aSize = 1048576 );
|
||||
~VBO_CONTAINER();
|
||||
|
||||
///< Maps size of free memory chunks to their offsets
|
||||
typedef std::pair<const unsigned int, unsigned int> Chunk;
|
||||
typedef std::multimap<const unsigned int, unsigned int> FreeChunkMap;
|
||||
|
||||
///< Maps size of reserved memory chunks to their owners (VBO_ITEMs)
|
||||
typedef std::pair<VBO_ITEM* const, Chunk> ReservedChunk;
|
||||
typedef std::multimap<VBO_ITEM* const, Chunk> ReservedChunkMap;
|
||||
|
||||
/**
|
||||
* Function StartItem()
|
||||
* Starts an unknown sized item. After calling the function it is possible to add vertices
|
||||
* using function Add().
|
||||
* @param aVboItem is the item that is going to store vertices in the container.
|
||||
*/
|
||||
void StartItem( VBO_ITEM* aVboItem );
|
||||
|
||||
/**
|
||||
* Function EndItem()
|
||||
* Marks current item as finished and returns unused memory to the pool. StartItem() function
|
||||
* has to be called first.
|
||||
*/
|
||||
void EndItem();
|
||||
|
||||
/**
|
||||
* Function Add()
|
||||
* Stores given number of vertices in the container for the specific VBO_ITEM.
|
||||
* @param aVboItem is the owner of the vertices.
|
||||
* @param aVertex are vertices data to be stored.
|
||||
* @param aSize is the number of vertices to be added.
|
||||
*/
|
||||
void Add( VBO_ITEM* aVboItem, const VBO_VERTEX* aVertex, unsigned int aSize = 1 );
|
||||
|
||||
/**
|
||||
* Function Free()
|
||||
* Frees the chunk reserved by the aVboItem.
|
||||
* @param aVboItem is the owner of the chunk to be freed.
|
||||
*/
|
||||
inline void Free( VBO_ITEM* aVboItem )
|
||||
{
|
||||
ReservedChunkMap::iterator it = m_reservedChunks.find( aVboItem );
|
||||
free( it );
|
||||
|
||||
// Dynamic memory freeing, there is no point in holding
|
||||
// a large amount of memory when there is no use for it
|
||||
if( m_freeSpace > ( m_currentSize / 2 ) )
|
||||
{
|
||||
resizeContainer( m_currentSize / 2 );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function GetAllVertices()
|
||||
* Returns all vertices stored in the container. It is especially useful for transferring
|
||||
* data to the GPU memory.
|
||||
*/
|
||||
VBO_VERTEX* GetAllVertices() const;
|
||||
|
||||
/**
|
||||
* Function GetVertices()
|
||||
* Returns vertices stored by the specific item.
|
||||
* @aVboItem is the specific item.
|
||||
*/
|
||||
VBO_VERTEX* GetVertices( const VBO_ITEM* aVboItem ) const;
|
||||
|
||||
/**
|
||||
* Function GetSize()
|
||||
* Returns amount of vertices currently stored in the container.
|
||||
*/
|
||||
inline int GetSize() const
|
||||
{
|
||||
return m_currentSize;
|
||||
}
|
||||
|
||||
private:
|
||||
///< Stores size & offset of free chunks.
|
||||
FreeChunkMap m_freeChunks;
|
||||
///< Stores owners (VBO_ITEM*) of reserved chunks and their size & offset.
|
||||
ReservedChunkMap m_reservedChunks;
|
||||
|
||||
/**
|
||||
* Function allocate()
|
||||
* Finds an offset where the number of vertices can be stored in a continous space. If there is
|
||||
* no such chunk, appropriate amount of memory is allocated first.
|
||||
* @param aVboItem is the owner of vertices to be stored.
|
||||
* @param aSize is the number of vertices to be stored.
|
||||
*/
|
||||
unsigned int allocate( VBO_ITEM* aVboItem, unsigned int aSize );
|
||||
|
||||
/**
|
||||
* Function getChunkSize()
|
||||
* Returns size of the given chunk (works both for reserved and free chunks).
|
||||
* @param aChunk is the chunk.
|
||||
*/
|
||||
inline int getChunkSize( const Chunk& aChunk ) const
|
||||
{
|
||||
return aChunk.first;
|
||||
}
|
||||
|
||||
inline int getChunkSize( const ReservedChunk& aChunk ) const
|
||||
{
|
||||
return aChunk.second.first;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function getChunkOffset()
|
||||
* Returns offset of the given chunk (works both for reserved and free chunks).
|
||||
* @param aChunk is the chunk.
|
||||
*/
|
||||
inline unsigned int getChunkOffset( const Chunk& aChunk ) const
|
||||
{
|
||||
return aChunk.second;
|
||||
}
|
||||
|
||||
inline unsigned int getChunkOffset( const ReservedChunk& aChunk ) const
|
||||
{
|
||||
return aChunk.second.second;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function getChunkOffset()
|
||||
* Upadtes offset of the given chunk (works both for reserved and free chunks).
|
||||
* !! IMPORTANT: it does not reallocate the chunk, it just changes its properties.
|
||||
* @param aChunk is the chunk.
|
||||
*/
|
||||
inline void setChunkOffset( Chunk& aChunk, unsigned int aOffset ) const
|
||||
{
|
||||
aChunk.second = aOffset;
|
||||
}
|
||||
|
||||
inline void setChunkOffset( ReservedChunk& aChunk, unsigned int aOffset ) const
|
||||
{
|
||||
aChunk.second.second = aOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function getChunkVboItem()
|
||||
* Returns owner of the given reserved chunk.
|
||||
* @param aChunk is the chunk.
|
||||
*/
|
||||
inline VBO_ITEM* getChunkVboItem( const ReservedChunk& aChunk ) const
|
||||
{
|
||||
return aChunk.first;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function defragment()
|
||||
* Removes empty spaces between chunks, so after that there is a long continous space
|
||||
* for storing vertices at the and of the container.
|
||||
* @return false in case of failure (eg. memory shortage)
|
||||
*/
|
||||
bool defragment( VBO_VERTEX* aTarget = NULL );
|
||||
|
||||
/**
|
||||
* Function resizeChunk()
|
||||
* Changes size of the chunk that stores vertices of aVboItem.
|
||||
* @param aVboItem is the item for which reserved space size should be changed.
|
||||
* @param aNewSize is the new size for the aVboItem, expressed in vertices number.
|
||||
*/
|
||||
void resizeChunk( VBO_ITEM* aVboItem, int aNewSize );
|
||||
|
||||
/**
|
||||
* Function resizeContainer()
|
||||
* Prepares a bigger container of a given size.
|
||||
* @param aNewSize is the new size of container, expressed in vertices
|
||||
* @return false in case of failure (eg. memory shortage)
|
||||
*/
|
||||
bool resizeContainer( unsigned int aNewSize );
|
||||
|
||||
/**
|
||||
* Function free()
|
||||
* Frees the space described in aChunk and returns it to the free space pool.
|
||||
* @param aChunk is a space to be freed.
|
||||
*/
|
||||
void free( const ReservedChunkMap::iterator& aChunk );
|
||||
|
||||
///< How many vertices we can store in the container
|
||||
unsigned int m_freeSpace;
|
||||
|
||||
///< How big is the current container, expressed in vertices
|
||||
unsigned int m_currentSize;
|
||||
|
||||
///< Actual storage memory
|
||||
VBO_VERTEX* m_vertices;
|
||||
|
||||
///< A flag saying if there is the item with an unknown size being added
|
||||
bool itemStarted;
|
||||
|
||||
///< Variables holding the state of the item currently being added
|
||||
unsigned int itemSize, itemChunkSize;
|
||||
VBO_ITEM* item;
|
||||
|
||||
/**
|
||||
* Function getPowerOf2()
|
||||
* Returns the nearest power of 2, bigger than aNumber.
|
||||
* @param aNumber is the number for which we look for a bigger power of 2.
|
||||
*/
|
||||
unsigned int getPowerOf2( unsigned int aNumber )
|
||||
{
|
||||
unsigned int power = 1;
|
||||
|
||||
while( power < aNumber && power )
|
||||
power <<= 1;
|
||||
|
||||
return power;
|
||||
}
|
||||
};
|
||||
} // namespace KiGfx
|
||||
|
||||
#endif /* VBO_CONTAINER_H_ */
|
|
@ -36,8 +36,6 @@
|
|||
|
||||
#include <cstddef>
|
||||
|
||||
#include <list>
|
||||
|
||||
namespace KiGfx
|
||||
{
|
||||
typedef struct VBO_VERTEX
|
||||
|
@ -45,12 +43,31 @@ typedef struct VBO_VERTEX
|
|||
GLfloat x, y, z; // Coordinates
|
||||
GLfloat r, g, b, a; // Color
|
||||
GLfloat shader[4]; // Shader type & params
|
||||
GLfloat _padding;
|
||||
|
||||
VBO_VERTEX()
|
||||
{}
|
||||
|
||||
VBO_VERTEX( const GLfloat aX, const GLfloat aY, const GLfloat aZ ) :
|
||||
x( aX ), y( aY ), z( aZ )
|
||||
{}
|
||||
|
||||
VBO_VERTEX( const GLfloat *aData ) :
|
||||
x( aData[0] ), y( aData[1] ), z( aData[2] )
|
||||
{}
|
||||
|
||||
operator GLfloat*()
|
||||
{
|
||||
return &x;
|
||||
}
|
||||
} VBO_VERTEX;
|
||||
|
||||
class VBO_CONTAINER;
|
||||
|
||||
class VBO_ITEM
|
||||
{
|
||||
public:
|
||||
VBO_ITEM();
|
||||
VBO_ITEM( VBO_CONTAINER* aContainer );
|
||||
~VBO_ITEM();
|
||||
|
||||
/**
|
||||
|
@ -60,7 +77,7 @@ public:
|
|||
* @param aVertex is a vertex to be added.
|
||||
* @param aShader is an attribute for shader.
|
||||
*/
|
||||
void PushVertex( const GLfloat* aVertex );
|
||||
void PushVertex( VBO_VERTEX* aVertex );
|
||||
|
||||
/**
|
||||
* Function PushVertices()
|
||||
|
@ -71,14 +88,14 @@ public:
|
|||
* @param aSize is an amount of vertices to be added.
|
||||
* @param aShader is an attribute for shader.
|
||||
*/
|
||||
void PushVertices( const GLfloat* aVertices, GLuint aSize );
|
||||
void PushVertices( VBO_VERTEX* aVertices, GLuint aSize );
|
||||
|
||||
/**
|
||||
* Function GetVertices()
|
||||
* Returns a pointer to the array containing all vertices.
|
||||
* @return Pointer to vertices packed in format {X, Y, Z, R, G, B, A}.
|
||||
*/
|
||||
GLfloat* GetVertices();
|
||||
VBO_VERTEX* GetVertices();
|
||||
|
||||
|
||||
/**
|
||||
|
@ -86,7 +103,7 @@ public:
|
|||
* Returns information about number of vertices stored.
|
||||
* @param Amount of vertices.
|
||||
*/
|
||||
inline int GetSize() const
|
||||
inline unsigned int GetSize() const
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
@ -96,7 +113,7 @@ public:
|
|||
* Sets data offset in the VBO.
|
||||
* @param aOffset is the offset expressed as a number of vertices.
|
||||
*/
|
||||
void SetOffset( int aOffset )
|
||||
void SetOffset( unsigned int aOffset )
|
||||
{
|
||||
m_offset = aOffset;
|
||||
}
|
||||
|
@ -106,7 +123,7 @@ public:
|
|||
* Returns data offset in the VBO.
|
||||
* @return Data offset expressed as a number of vertices.
|
||||
*/
|
||||
inline int GetOffset() const
|
||||
inline unsigned int GetOffset() const
|
||||
{
|
||||
return m_offset;
|
||||
}
|
||||
|
@ -156,16 +173,8 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
inline void FreeVerticesData()
|
||||
{
|
||||
if( m_vertices && !m_isDirty )
|
||||
{
|
||||
delete[] m_vertices;
|
||||
m_vertices = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
///< Informs the container that there will be no more vertices for the current VBO_ITEM
|
||||
void Finish();
|
||||
|
||||
///< Data organization information for vertices {X,Y,Z,R,G,B,A} (@see VBO_VERTEX).
|
||||
static const int VertByteSize = sizeof(VBO_VERTEX);
|
||||
|
@ -191,40 +200,24 @@ public:
|
|||
static const int IndByteSize = sizeof(GLuint);
|
||||
|
||||
private:
|
||||
///< Contains vertices coordinates and colors.
|
||||
///< Packed by 7 floats for each vertex: {X, Y, Z, R, G, B, A}
|
||||
GLfloat* m_vertices;
|
||||
///< Offset and size of data stored in the VBO_CONTAINER.
|
||||
unsigned int m_offset;
|
||||
unsigned int m_size;
|
||||
|
||||
///< Lists of data blocks storing vertices
|
||||
std::list<VBO_VERTEX*> m_vertBlocks;
|
||||
|
||||
///< Pointers to current blocks that should be used for storing data
|
||||
VBO_VERTEX* m_vertPtr;
|
||||
|
||||
///< How many vertices can be stored in the current buffer
|
||||
int m_spaceLeft;
|
||||
///< Number of vertices stored in a single block
|
||||
static const int BLOCK_SIZE = 256;
|
||||
///< Creates a new block for storing vertices data
|
||||
void useNewBlock();
|
||||
///< Prepares a continuous block of data that can be copied to graphics card buffer.
|
||||
void prepareFinal();
|
||||
|
||||
///< Offset and size of data in VBO.
|
||||
int m_offset;
|
||||
int m_size;
|
||||
///< Storage for vertices.
|
||||
VBO_CONTAINER* m_container;
|
||||
|
||||
///< Color used for new vertices pushed.
|
||||
GLfloat m_color[ColorStride];
|
||||
GLfloat m_color[ColorStride];
|
||||
|
||||
///< Shader and its parameters used for new vertices pushed
|
||||
GLfloat m_shader[ShaderStride];
|
||||
GLfloat m_shader[ShaderStride];
|
||||
|
||||
///< Flag telling if the item should be recached in VBO or not.
|
||||
bool m_isDirty;
|
||||
bool m_isDirty;
|
||||
|
||||
///< Current transform matrix applied for every new vertex pushed.
|
||||
const glm::mat4* m_transform;
|
||||
const glm::mat4* m_transform;
|
||||
};
|
||||
} // namespace KiGfx
|
||||
|
||||
|
|
|
@ -68,7 +68,7 @@ public:
|
|||
ALL = 0xff
|
||||
};
|
||||
|
||||
VIEW_ITEM() : m_view( NULL ), m_viewVisible( true ), m_groupsSize( 0 ) {}
|
||||
VIEW_ITEM() : m_view( NULL ), m_viewVisible( true ), m_groups( NULL ), m_groupsSize( 0 ) {}
|
||||
|
||||
/**
|
||||
* Destructor. For dynamic views, removes the item from the view.
|
||||
|
@ -76,6 +76,7 @@ public:
|
|||
virtual ~VIEW_ITEM()
|
||||
{
|
||||
ViewRelease();
|
||||
delete[] m_groups;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue