791 lines
24 KiB
C++
791 lines
24 KiB
C++
/*
|
|
* 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::DrawAllCameraCulled( 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 );
|
|
}
|
|
}
|