|
|
/*
* This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt> * Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors. * * 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 */
#include "layer_triangles.h"
#include "../raytracing/ray.h"
#include <wx/debug.h> // For the wxASSERT
#include <mutex>
TRIANGLE_LIST::TRIANGLE_LIST( unsigned int aNrReservedTriangles, bool aReserveNormals ){ wxASSERT( aNrReservedTriangles > 0 );
m_vertexs.clear(); m_normals.clear();
m_vertexs.reserve( aNrReservedTriangles * 3 );
if( aReserveNormals ) m_normals.reserve( aNrReservedTriangles * 3 );}
void TRIANGLE_LIST::Reserve_More( unsigned int aNrReservedTriangles, bool aReserveNormals ){ m_vertexs.reserve( m_vertexs.size() + aNrReservedTriangles * 3 );
if( aReserveNormals ) m_normals.reserve( m_normals.size() + aNrReservedTriangles * 3 );}
void TRIANGLE_LIST::AddQuad( const SFVEC3F& aV1, const SFVEC3F& aV2, const SFVEC3F& aV3, const SFVEC3F& aV4 ){ m_vertexs.push_back( aV1 ); m_vertexs.push_back( aV2 ); m_vertexs.push_back( aV3 );
m_vertexs.push_back( aV3 ); m_vertexs.push_back( aV4 ); m_vertexs.push_back( aV1 );}
void TRIANGLE_LIST::AddTriangle( const SFVEC3F& aV1, const SFVEC3F& aV2, const SFVEC3F& aV3 ){ m_vertexs.push_back( aV1 ); m_vertexs.push_back( aV2 ); m_vertexs.push_back( aV3 );}
void TRIANGLE_LIST::AddNormal( const SFVEC3F& aN1, const SFVEC3F& aN2, const SFVEC3F& aN3 ){ m_normals.push_back( aN1 ); m_normals.push_back( aN2 ); m_normals.push_back( aN3 );}
void TRIANGLE_LIST::AddNormal( const SFVEC3F& aN1, const SFVEC3F& aN2, const SFVEC3F& aN3, const SFVEC3F& aN4 ){ m_normals.push_back( aN1 ); m_normals.push_back( aN2 ); m_normals.push_back( aN3 );
m_normals.push_back( aN3 ); m_normals.push_back( aN4 ); m_normals.push_back( aN1 );}
TRIANGLE_DISPLAY_LIST::TRIANGLE_DISPLAY_LIST( unsigned int aNrReservedTriangles ){ wxASSERT( aNrReservedTriangles > 0 );
m_layer_top_segment_ends = new TRIANGLE_LIST( aNrReservedTriangles, false ); m_layer_top_triangles = new TRIANGLE_LIST( aNrReservedTriangles, false ); m_layer_middle_contourns_quads = new TRIANGLE_LIST( aNrReservedTriangles, true ); m_layer_bot_triangles = new TRIANGLE_LIST( aNrReservedTriangles, false ); m_layer_bot_segment_ends = new TRIANGLE_LIST( aNrReservedTriangles, false );}
TRIANGLE_DISPLAY_LIST::~TRIANGLE_DISPLAY_LIST(){ delete m_layer_top_segment_ends; m_layer_top_segment_ends = nullptr;
delete m_layer_top_triangles; m_layer_top_triangles = nullptr;
delete m_layer_middle_contourns_quads; m_layer_middle_contourns_quads = nullptr;
delete m_layer_bot_triangles; m_layer_bot_triangles = nullptr;
delete m_layer_bot_segment_ends; m_layer_bot_segment_ends = nullptr;}
void TRIANGLE_DISPLAY_LIST::AddToMiddleContourns( const std::vector< SFVEC2F >& aContournPoints, float zBot, float zTop, bool aInvertFaceDirection, const BVH_CONTAINER_2D* aThroughHoles ){ if( aContournPoints.size() >= 4 ) { // Calculate normals of each segment of the contourn
std::vector< SFVEC2F > contournNormals;
contournNormals.clear(); contournNormals.resize( aContournPoints.size() - 1 );
if( aInvertFaceDirection ) { for( unsigned int i = 0; i < ( aContournPoints.size() - 1 ); ++i ) { const SFVEC2F& v0 = aContournPoints[i + 0]; const SFVEC2F& v1 = aContournPoints[i + 1]; const SFVEC2F n = glm::normalize( v1 - v0 );
contournNormals[i] = SFVEC2F( n.y,-n.x ); } } else { for( unsigned int i = 0; i < ( aContournPoints.size() - 1 ); ++i ) { const SFVEC2F& v0 = aContournPoints[i + 0]; const SFVEC2F& v1 = aContournPoints[i + 1]; const SFVEC2F n = glm::normalize( v1 - v0 );
contournNormals[i] = SFVEC2F( -n.y, n.x ); } }
if( aInvertFaceDirection ) std::swap( zBot, zTop );
const unsigned int nContournsToProcess = ( aContournPoints.size() - 1 );
for( unsigned int i = 0; i < nContournsToProcess; ++i ) { SFVEC2F lastNormal;
if( i > 0 ) lastNormal = contournNormals[i - 1]; else lastNormal = contournNormals[nContournsToProcess - 1];
SFVEC2F n0 = contournNormals[i];
// Only interpolate the normal if the angle is closer
if( glm::dot( n0, lastNormal ) > 0.5f ) n0 = glm::normalize( n0 + lastNormal );
SFVEC2F nextNormal;
if( i < (nContournsToProcess - 1) ) nextNormal = contournNormals[i + 1]; else nextNormal = contournNormals[0];
SFVEC2F n1 = contournNormals[i];
if( glm::dot( n1, nextNormal ) > 0.5f ) n1 = glm::normalize( n1 + nextNormal );
const SFVEC3F n3d0 = SFVEC3F( n0.x, n0.y, 0.0f ); const SFVEC3F n3d1 = SFVEC3F( n1.x, n1.y, 0.0f );
const SFVEC2F& v0 = aContournPoints[i + 0]; const SFVEC2F& v1 = aContournPoints[i + 1];
if( aThroughHoles && aThroughHoles->IntersectAny( RAYSEG2D( v0, v1 ) ) ) { continue; } else { std::lock_guard<std::mutex> lock( m_middle_layer_lock ); m_layer_middle_contourns_quads->AddQuad( SFVEC3F( v0.x, v0.y, zTop ), SFVEC3F( v1.x, v1.y, zTop ), SFVEC3F( v1.x, v1.y, zBot ), SFVEC3F( v0.x, v0.y, zBot ) );
m_layer_middle_contourns_quads->AddNormal( n3d0, n3d1, n3d1, n3d0 ); } } }}
void TRIANGLE_DISPLAY_LIST::AddToMiddleContourns( const SHAPE_LINE_CHAIN& outlinePath, float zBot, float zTop, double aBiuTo3Du, bool aInvertFaceDirection, const BVH_CONTAINER_2D* aThroughHoles ){ std::vector< SFVEC2F >contournPoints;
contournPoints.clear(); contournPoints.reserve( outlinePath.PointCount() + 2 );
const VECTOR2I& firstV = outlinePath.CPoint( 0 );
SFVEC2F lastV = SFVEC2F( firstV.x * aBiuTo3Du, -firstV.y * aBiuTo3Du );
contournPoints.push_back( lastV );
for( unsigned int i = 1; i < (unsigned int)outlinePath.PointCount(); ++i ) { const VECTOR2I& v = outlinePath.CPoint( i );
const SFVEC2F vf = SFVEC2F( v.x * aBiuTo3Du, -v.y * aBiuTo3Du );
if( vf != lastV ) // Do not add repeated points
{ lastV = vf; contournPoints.push_back( vf ); } }
// Add first position fo the list to close the path
if( lastV != contournPoints[0] ) contournPoints.push_back( contournPoints[0] );
AddToMiddleContourns( contournPoints, zBot, zTop, aInvertFaceDirection, aThroughHoles );}
void TRIANGLE_DISPLAY_LIST::AddToMiddleContourns( const SHAPE_POLY_SET& aPolySet, float zBot, float zTop, double aBiuTo3Du, bool aInvertFaceDirection, const BVH_CONTAINER_2D* aThroughHoles ){ if( aPolySet.OutlineCount() == 0 ) return;
// Calculate an estimation of points to reserve
unsigned int nrContournPointsToReserve = 0;
for( int i = 0; i < aPolySet.OutlineCount(); ++i ) { const SHAPE_LINE_CHAIN& pathOutline = aPolySet.COutline( i );
nrContournPointsToReserve += pathOutline.PointCount();
for( int h = 0; h < aPolySet.HoleCount( i ); ++h ) { const SHAPE_LINE_CHAIN& hole = aPolySet.CHole( i, h );
nrContournPointsToReserve += hole.PointCount(); } }
// Request to reserve more space
m_layer_middle_contourns_quads->Reserve_More( nrContournPointsToReserve * 2, true );
for( int i = 0; i < aPolySet.OutlineCount(); i++ ) { // Add outline
const SHAPE_LINE_CHAIN& pathOutline = aPolySet.COutline( i );
AddToMiddleContourns( pathOutline, zBot, zTop, aBiuTo3Du, aInvertFaceDirection, aThroughHoles );
// Add holes for this outline
for( int h = 0; h < aPolySet.HoleCount( i ); ++h ) { const SHAPE_LINE_CHAIN& hole = aPolySet.CHole( i, h ); AddToMiddleContourns( hole, zBot, zTop, aBiuTo3Du, aInvertFaceDirection, aThroughHoles ); } }}
OPENGL_RENDER_LIST::OPENGL_RENDER_LIST( const TRIANGLE_DISPLAY_LIST& aLayerTriangles, GLuint aTextureIndexForSegEnds, float aZBot, float aZTop ){ m_zBot = aZBot; m_zTop = aZTop;
m_layer_top_segment_ends = 0; m_layer_top_triangles = 0; m_layer_middle_contourns_quads = 0; m_layer_bot_triangles = 0; m_layer_bot_segment_ends = 0;
if( aTextureIndexForSegEnds ) { wxASSERT( glIsTexture( aTextureIndexForSegEnds ) );
if( glIsTexture( aTextureIndexForSegEnds ) ) { m_layer_top_segment_ends = generate_top_or_bot_seg_ends( aLayerTriangles.m_layer_top_segment_ends, true, aTextureIndexForSegEnds );
m_layer_bot_segment_ends = generate_top_or_bot_seg_ends( aLayerTriangles.m_layer_bot_segment_ends, false, aTextureIndexForSegEnds ); } }
m_layer_top_triangles = generate_top_or_bot_triangles( aLayerTriangles.m_layer_top_triangles, true );
m_layer_bot_triangles = generate_top_or_bot_triangles( aLayerTriangles.m_layer_bot_triangles, false );
if( aLayerTriangles.m_layer_middle_contourns_quads->GetVertexSize() > 0 ) { m_layer_middle_contourns_quads = generate_middle_triangles( aLayerTriangles.m_layer_middle_contourns_quads ); }
m_draw_it_transparent = false; m_haveTransformation = false; m_zPositionTransformation = 0.0f; m_zScaleTransformation = 0.0f;}
OPENGL_RENDER_LIST::~OPENGL_RENDER_LIST(){ if( glIsList( m_layer_top_segment_ends ) ) glDeleteLists( m_layer_top_segment_ends, 1 );
if( glIsList( m_layer_top_triangles ) ) glDeleteLists( m_layer_top_triangles, 1 );
if( glIsList( m_layer_middle_contourns_quads ) ) glDeleteLists( m_layer_middle_contourns_quads, 1 );
if( glIsList( m_layer_bot_triangles ) ) glDeleteLists( m_layer_bot_triangles, 1 );
if( glIsList( m_layer_bot_segment_ends ) ) glDeleteLists( m_layer_bot_segment_ends, 1 );
m_layer_top_segment_ends = 0; m_layer_top_triangles = 0; m_layer_middle_contourns_quads = 0; m_layer_bot_triangles = 0; m_layer_bot_segment_ends = 0;}
void OPENGL_RENDER_LIST::DrawTopAndMiddle() const{ beginTransformation();
if( glIsList( m_layer_middle_contourns_quads ) ) glCallList( m_layer_middle_contourns_quads );
if( glIsList( m_layer_top_triangles ) ) glCallList( m_layer_top_triangles );
if( glIsList( m_layer_top_segment_ends ) ) glCallList( m_layer_top_segment_ends );
endTransformation();}
void OPENGL_RENDER_LIST::DrawBotAndMiddle() const{ beginTransformation();
if( glIsList( m_layer_middle_contourns_quads ) ) glCallList( m_layer_middle_contourns_quads );
if( glIsList( m_layer_bot_triangles ) ) glCallList( m_layer_bot_triangles );
if( glIsList( m_layer_bot_segment_ends ) ) glCallList( m_layer_bot_segment_ends );
endTransformation();}
void OPENGL_RENDER_LIST::DrawTop() const{ beginTransformation();
if( glIsList( m_layer_top_triangles ) ) glCallList( m_layer_top_triangles );
if( glIsList( m_layer_top_segment_ends ) ) glCallList( m_layer_top_segment_ends );
endTransformation();}
void OPENGL_RENDER_LIST::DrawBot() const{ beginTransformation();
if( glIsList( m_layer_bot_triangles ) ) glCallList( m_layer_bot_triangles );
if( glIsList( m_layer_bot_segment_ends ) ) glCallList( m_layer_bot_segment_ends );
endTransformation();}
void OPENGL_RENDER_LIST::DrawMiddle() const{ beginTransformation();
if( glIsList( m_layer_middle_contourns_quads ) ) glCallList( m_layer_middle_contourns_quads );
endTransformation();}
void OPENGL_RENDER_LIST::DrawAll( bool aDrawMiddle ) const{ beginTransformation();
if( aDrawMiddle ) if( glIsList( m_layer_middle_contourns_quads ) ) glCallList( m_layer_middle_contourns_quads );
if( glIsList( m_layer_top_triangles ) ) glCallList( m_layer_top_triangles );
if( glIsList( m_layer_bot_triangles ) ) glCallList( m_layer_bot_triangles );
if( glIsList( m_layer_top_segment_ends ) ) glCallList( m_layer_top_segment_ends );
if( glIsList( m_layer_bot_segment_ends ) ) glCallList( m_layer_bot_segment_ends );
endTransformation();}
void OPENGL_RENDER_LIST::DrawAllCameraCulled( float zCameraPos, bool aDrawMiddle ) const{ zCameraPos = m_haveTransformation ? ( ( zCameraPos - m_zPositionTransformation ) / m_zScaleTransformation ) : zCameraPos;
if( aDrawMiddle ) DrawMiddle();
if( zCameraPos > m_zTop ) { DrawTop(); } else { if( zCameraPos < m_zBot ) { DrawBot(); } else { // If camera is in the middle dont draw it.
} }}
void OPENGL_RENDER_LIST::DrawAllCameraCulledSubtractLayer( bool aDrawMiddle, const OPENGL_RENDER_LIST* aLayerToSubtractA, const OPENGL_RENDER_LIST* aLayerToSubtractB, const OPENGL_RENDER_LIST* aLayerToSubtractC, const OPENGL_RENDER_LIST* aLayerToSubtractD ) const{ glClearStencil( 0x00 ); glClear( GL_STENCIL_BUFFER_BIT );
glEnable( GL_CULL_FACE ); glCullFace( GL_BACK );
glDisable( GL_DEPTH_TEST ); glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE ); glDepthMask( GL_FALSE ); glEnable( GL_STENCIL_TEST ); glStencilFunc( GL_ALWAYS, 1, 0 ); glStencilOp( GL_KEEP, GL_KEEP, GL_REPLACE );
if( aLayerToSubtractA ) aLayerToSubtractA->DrawBot();
if( aLayerToSubtractB ) aLayerToSubtractB->DrawBot();
if( aLayerToSubtractC ) aLayerToSubtractC->DrawBot();
if( aLayerToSubtractD ) aLayerToSubtractD->DrawBot();
glEnable(GL_DEPTH_TEST); glDepthMask(GL_TRUE);
glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE ); glStencilFunc( GL_EQUAL, 0, 1 ); glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP ); DrawBot();
glDisable( GL_DEPTH_TEST ); glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE ); glDepthMask( GL_FALSE ); glEnable( GL_STENCIL_TEST ); glStencilFunc( GL_ALWAYS, 2, 0 ); glStencilOp( GL_KEEP, GL_KEEP, GL_REPLACE );
if( aLayerToSubtractA ) aLayerToSubtractA->DrawTop();
if( aLayerToSubtractB ) aLayerToSubtractB->DrawTop();
if( aLayerToSubtractC ) aLayerToSubtractC->DrawTop();
if( aLayerToSubtractD ) aLayerToSubtractD->DrawTop();
glEnable(GL_DEPTH_TEST); glDepthMask(GL_TRUE); glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE ); glStencilFunc( GL_NOTEQUAL, 2, 0x03 ); glStencilOp( GL_KEEP, GL_KEEP, GL_INCR ); DrawTop();
if( aDrawMiddle ) DrawMiddle();
glLightModeli( GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE );
glCullFace( GL_FRONT ); glStencilFunc( GL_GEQUAL, 3, 0x03 ); glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP ); glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
if( aDrawMiddle ) { if( aLayerToSubtractA ) aLayerToSubtractA->DrawMiddle(); }
glLightModeli( GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE );
glCullFace( GL_BACK ); glDisable( GL_STENCIL_TEST );}
void OPENGL_RENDER_LIST::ApplyScalePosition( float aZposition, float aZscale ){ wxCHECK2( aZscale > FLT_EPSILON, aZscale = FLT_EPSILON + 1 );
m_zPositionTransformation = aZposition; m_zScaleTransformation = aZscale; m_haveTransformation = true;}
void OPENGL_RENDER_LIST::SetItIsTransparent( bool aSetTransparent ){ m_draw_it_transparent = aSetTransparent;}
GLuint OPENGL_RENDER_LIST::generate_top_or_bot_seg_ends( const TRIANGLE_LIST* aTriangleContainer, bool aIsNormalUp, GLuint aTextureId ) const{ wxASSERT( aTriangleContainer != nullptr );
wxASSERT( ( aTriangleContainer->GetVertexSize() % 3 ) == 0 );
// Top and Bot dont have normals array stored in container
wxASSERT( aTriangleContainer->GetNormalsSize() == 0 );
if( ( aTriangleContainer->GetVertexSize() > 0 ) && ( ( aTriangleContainer->GetVertexSize() % 3 ) == 0 ) ) { GLuint listIdx = glGenLists( 1 );
if( glIsList( listIdx ) ) { // Prepare an array of UV text coordinates
SFVEC2F* uvArray = new SFVEC2F[aTriangleContainer->GetVertexSize()];
for( unsigned int i = 0; i < aTriangleContainer->GetVertexSize(); i += 3 ) { uvArray[i + 0] = SFVEC2F( 1.0f, 0.0f ); uvArray[i + 1] = SFVEC2F( 0.0f, 1.0f ); uvArray[i + 2] = SFVEC2F( 0.0f, 0.0f ); }
glEnableClientState( GL_TEXTURE_COORD_ARRAY ); glDisableClientState( GL_COLOR_ARRAY ); glDisableClientState( GL_NORMAL_ARRAY ); glEnableClientState( GL_VERTEX_ARRAY ); glVertexPointer( 3, GL_FLOAT, 0, aTriangleContainer->GetVertexPointer() ); glTexCoordPointer( 2, GL_FLOAT, 0, uvArray );
glNewList( listIdx, GL_COMPILE );
glDisable( GL_COLOR_MATERIAL );
glEnable( GL_TEXTURE_2D ); glBindTexture( GL_TEXTURE_2D, aTextureId );
glAlphaFunc( GL_GREATER, 0.2f ); glEnable( GL_ALPHA_TEST );
glNormal3f( 0.0f, 0.0f, aIsNormalUp?1.0f:-1.0f );
glDrawArrays( GL_TRIANGLES, 0, aTriangleContainer->GetVertexSize() );
glBindTexture( GL_TEXTURE_2D, 0 ); glDisable( GL_TEXTURE_2D ); glDisable( GL_ALPHA_TEST ); glDisable( GL_BLEND );
glEndList();
glDisableClientState( GL_VERTEX_ARRAY ); glDisableClientState( GL_TEXTURE_COORD_ARRAY );
delete [] uvArray; return listIdx; } }
return 0;}
GLuint OPENGL_RENDER_LIST::generate_top_or_bot_triangles( const TRIANGLE_LIST* aTriangleContainer, bool aIsNormalUp ) const{ wxASSERT( aTriangleContainer != nullptr );
wxASSERT( ( aTriangleContainer->GetVertexSize() % 3 ) == 0 );
// Top and Bot dont have normals array stored in container
wxASSERT( aTriangleContainer->GetNormalsSize() == 0 );
if( ( aTriangleContainer->GetVertexSize() > 0 ) && ( ( aTriangleContainer->GetVertexSize() % 3 ) == 0 ) ) { const GLuint listIdx = glGenLists( 1 );
if( glIsList( listIdx ) ) { glDisableClientState( GL_TEXTURE_COORD_ARRAY ); glDisableClientState( GL_COLOR_ARRAY ); glDisableClientState( GL_NORMAL_ARRAY ); glEnableClientState( GL_VERTEX_ARRAY ); glVertexPointer( 3, GL_FLOAT, 0, aTriangleContainer->GetVertexPointer() );
glNewList( listIdx, GL_COMPILE );
setBlendfunction();
glNormal3f( 0.0f, 0.0f, aIsNormalUp?1.0f:-1.0f );
glDrawArrays( GL_TRIANGLES, 0, aTriangleContainer->GetVertexSize() );
glDisable( GL_BLEND ); glEndList();
glDisableClientState( GL_VERTEX_ARRAY );
return listIdx; } }
return 0;}
GLuint OPENGL_RENDER_LIST::generate_middle_triangles( const TRIANGLE_LIST* aTriangleContainer ) const{ wxASSERT( aTriangleContainer != nullptr );
// We expect that it is a multiple of 3 vertex
wxASSERT( ( aTriangleContainer->GetVertexSize() % 3 ) == 0 );
// We expect that it is a multiple of 6 vertex (because we expect to add quads)
wxASSERT( (aTriangleContainer->GetVertexSize() % 6 ) == 0 );
// We expect that there are normals with same size as vertex
wxASSERT( aTriangleContainer->GetNormalsSize() == aTriangleContainer->GetVertexSize() );
if( ( aTriangleContainer->GetVertexSize() > 0 ) && ( ( aTriangleContainer->GetVertexSize() % 3 ) == 0 ) && ( ( aTriangleContainer->GetVertexSize() % 6 ) == 0 ) && ( aTriangleContainer->GetNormalsSize() == aTriangleContainer->GetVertexSize() ) ) { const GLuint listIdx = glGenLists( 1 );
if( glIsList( listIdx ) ) { glDisableClientState( GL_TEXTURE_COORD_ARRAY ); glDisableClientState( GL_COLOR_ARRAY ); glEnableClientState( GL_NORMAL_ARRAY ); glEnableClientState( GL_VERTEX_ARRAY ); glVertexPointer( 3, GL_FLOAT, 0, aTriangleContainer->GetVertexPointer() ); glNormalPointer( GL_FLOAT, 0, aTriangleContainer->GetNormalsPointer() );
glNewList( listIdx, GL_COMPILE );
setBlendfunction();
glDrawArrays( GL_TRIANGLES, 0, aTriangleContainer->GetVertexSize() );
glDisable( GL_BLEND ); glEndList();
glDisableClientState( GL_VERTEX_ARRAY ); glDisableClientState( GL_NORMAL_ARRAY );
return listIdx; } }
return 0;}
void OPENGL_RENDER_LIST::endTransformation() const{ if( m_haveTransformation ) { glPopMatrix(); }}
void OPENGL_RENDER_LIST::setBlendfunction() const{ glEnable( GL_BLEND ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );}
void OPENGL_RENDER_LIST::beginTransformation() const{ if( m_haveTransformation ) { glPushMatrix(); glTranslatef( 0.0f, 0.0f, m_zPositionTransformation ); glScalef( 1.0f, 1.0f, m_zScaleTransformation ); }}
|