You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

790 lines
24 KiB

  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
  5. * Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors.
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License
  9. * as published by the Free Software Foundation; either version 2
  10. * of the License, or (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, you may find one here:
  19. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  20. * or you may search the http://www.gnu.org website for the version 2 license,
  21. * or you may write to the Free Software Foundation, Inc.,
  22. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  23. */
  24. #include "layer_triangles.h"
  25. #include "../raytracing/ray.h"
  26. #include <wx/debug.h> // For the wxASSERT
  27. #include <mutex>
  28. TRIANGLE_LIST::TRIANGLE_LIST( unsigned int aNrReservedTriangles, bool aReserveNormals )
  29. {
  30. wxASSERT( aNrReservedTriangles > 0 );
  31. m_vertexs.clear();
  32. m_normals.clear();
  33. m_vertexs.reserve( aNrReservedTriangles * 3 );
  34. if( aReserveNormals )
  35. m_normals.reserve( aNrReservedTriangles * 3 );
  36. }
  37. void TRIANGLE_LIST::Reserve_More( unsigned int aNrReservedTriangles, bool aReserveNormals )
  38. {
  39. m_vertexs.reserve( m_vertexs.size() + aNrReservedTriangles * 3 );
  40. if( aReserveNormals )
  41. m_normals.reserve( m_normals.size() + aNrReservedTriangles * 3 );
  42. }
  43. void TRIANGLE_LIST::AddQuad( const SFVEC3F& aV1, const SFVEC3F& aV2, const SFVEC3F& aV3,
  44. const SFVEC3F& aV4 )
  45. {
  46. m_vertexs.push_back( aV1 );
  47. m_vertexs.push_back( aV2 );
  48. m_vertexs.push_back( aV3 );
  49. m_vertexs.push_back( aV3 );
  50. m_vertexs.push_back( aV4 );
  51. m_vertexs.push_back( aV1 );
  52. }
  53. void TRIANGLE_LIST::AddTriangle( const SFVEC3F& aV1, const SFVEC3F& aV2, const SFVEC3F& aV3 )
  54. {
  55. m_vertexs.push_back( aV1 );
  56. m_vertexs.push_back( aV2 );
  57. m_vertexs.push_back( aV3 );
  58. }
  59. void TRIANGLE_LIST::AddNormal( const SFVEC3F& aN1, const SFVEC3F& aN2, const SFVEC3F& aN3 )
  60. {
  61. m_normals.push_back( aN1 );
  62. m_normals.push_back( aN2 );
  63. m_normals.push_back( aN3 );
  64. }
  65. void TRIANGLE_LIST::AddNormal( const SFVEC3F& aN1, const SFVEC3F& aN2, const SFVEC3F& aN3,
  66. const SFVEC3F& aN4 )
  67. {
  68. m_normals.push_back( aN1 );
  69. m_normals.push_back( aN2 );
  70. m_normals.push_back( aN3 );
  71. m_normals.push_back( aN3 );
  72. m_normals.push_back( aN4 );
  73. m_normals.push_back( aN1 );
  74. }
  75. TRIANGLE_DISPLAY_LIST::TRIANGLE_DISPLAY_LIST( unsigned int aNrReservedTriangles )
  76. {
  77. wxASSERT( aNrReservedTriangles > 0 );
  78. m_layer_top_segment_ends = new TRIANGLE_LIST( aNrReservedTriangles, false );
  79. m_layer_top_triangles = new TRIANGLE_LIST( aNrReservedTriangles, false );
  80. m_layer_middle_contourns_quads = new TRIANGLE_LIST( aNrReservedTriangles, true );
  81. m_layer_bot_triangles = new TRIANGLE_LIST( aNrReservedTriangles, false );
  82. m_layer_bot_segment_ends = new TRIANGLE_LIST( aNrReservedTriangles, false );
  83. }
  84. TRIANGLE_DISPLAY_LIST::~TRIANGLE_DISPLAY_LIST()
  85. {
  86. delete m_layer_top_segment_ends;
  87. m_layer_top_segment_ends = nullptr;
  88. delete m_layer_top_triangles;
  89. m_layer_top_triangles = nullptr;
  90. delete m_layer_middle_contourns_quads;
  91. m_layer_middle_contourns_quads = nullptr;
  92. delete m_layer_bot_triangles;
  93. m_layer_bot_triangles = nullptr;
  94. delete m_layer_bot_segment_ends;
  95. m_layer_bot_segment_ends = nullptr;
  96. }
  97. void TRIANGLE_DISPLAY_LIST::AddToMiddleContourns( const std::vector< SFVEC2F >& aContournPoints,
  98. float zBot, float zTop, bool aInvertFaceDirection,
  99. const BVH_CONTAINER_2D* aThroughHoles )
  100. {
  101. if( aContournPoints.size() >= 4 )
  102. {
  103. // Calculate normals of each segment of the contourn
  104. std::vector< SFVEC2F > contournNormals;
  105. contournNormals.clear();
  106. contournNormals.resize( aContournPoints.size() - 1 );
  107. if( aInvertFaceDirection )
  108. {
  109. for( unsigned int i = 0; i < ( aContournPoints.size() - 1 ); ++i )
  110. {
  111. const SFVEC2F& v0 = aContournPoints[i + 0];
  112. const SFVEC2F& v1 = aContournPoints[i + 1];
  113. const SFVEC2F n = glm::normalize( v1 - v0 );
  114. contournNormals[i] = SFVEC2F( n.y,-n.x );
  115. }
  116. }
  117. else
  118. {
  119. for( unsigned int i = 0; i < ( aContournPoints.size() - 1 ); ++i )
  120. {
  121. const SFVEC2F& v0 = aContournPoints[i + 0];
  122. const SFVEC2F& v1 = aContournPoints[i + 1];
  123. const SFVEC2F n = glm::normalize( v1 - v0 );
  124. contournNormals[i] = SFVEC2F( -n.y, n.x );
  125. }
  126. }
  127. if( aInvertFaceDirection )
  128. std::swap( zBot, zTop );
  129. const unsigned int nContournsToProcess = ( aContournPoints.size() - 1 );
  130. for( unsigned int i = 0; i < nContournsToProcess; ++i )
  131. {
  132. SFVEC2F lastNormal;
  133. if( i > 0 )
  134. lastNormal = contournNormals[i - 1];
  135. else
  136. lastNormal = contournNormals[nContournsToProcess - 1];
  137. SFVEC2F n0 = contournNormals[i];
  138. // Only interpolate the normal if the angle is closer
  139. if( glm::dot( n0, lastNormal ) > 0.5f )
  140. n0 = glm::normalize( n0 + lastNormal );
  141. SFVEC2F nextNormal;
  142. if( i < (nContournsToProcess - 1) )
  143. nextNormal = contournNormals[i + 1];
  144. else
  145. nextNormal = contournNormals[0];
  146. SFVEC2F n1 = contournNormals[i];
  147. if( glm::dot( n1, nextNormal ) > 0.5f )
  148. n1 = glm::normalize( n1 + nextNormal );
  149. const SFVEC3F n3d0 = SFVEC3F( n0.x, n0.y, 0.0f );
  150. const SFVEC3F n3d1 = SFVEC3F( n1.x, n1.y, 0.0f );
  151. const SFVEC2F& v0 = aContournPoints[i + 0];
  152. const SFVEC2F& v1 = aContournPoints[i + 1];
  153. if( aThroughHoles && aThroughHoles->IntersectAny( RAYSEG2D( v0, v1 ) ) )
  154. {
  155. continue;
  156. }
  157. else
  158. {
  159. std::lock_guard<std::mutex> lock( m_middle_layer_lock );
  160. m_layer_middle_contourns_quads->AddQuad( SFVEC3F( v0.x, v0.y, zTop ),
  161. SFVEC3F( v1.x, v1.y, zTop ),
  162. SFVEC3F( v1.x, v1.y, zBot ),
  163. SFVEC3F( v0.x, v0.y, zBot ) );
  164. m_layer_middle_contourns_quads->AddNormal( n3d0, n3d1, n3d1, n3d0 );
  165. }
  166. }
  167. }
  168. }
  169. void TRIANGLE_DISPLAY_LIST::AddToMiddleContourns( const SHAPE_LINE_CHAIN& outlinePath, float zBot,
  170. float zTop, double aBiuTo3Du,
  171. bool aInvertFaceDirection,
  172. const BVH_CONTAINER_2D* aThroughHoles )
  173. {
  174. std::vector< SFVEC2F >contournPoints;
  175. contournPoints.clear();
  176. contournPoints.reserve( outlinePath.PointCount() + 2 );
  177. const VECTOR2I& firstV = outlinePath.CPoint( 0 );
  178. SFVEC2F lastV = SFVEC2F( firstV.x * aBiuTo3Du, -firstV.y * aBiuTo3Du );
  179. contournPoints.push_back( lastV );
  180. for( unsigned int i = 1; i < (unsigned int)outlinePath.PointCount(); ++i )
  181. {
  182. const VECTOR2I& v = outlinePath.CPoint( i );
  183. const SFVEC2F vf = SFVEC2F( v.x * aBiuTo3Du, -v.y * aBiuTo3Du );
  184. if( vf != lastV ) // Do not add repeated points
  185. {
  186. lastV = vf;
  187. contournPoints.push_back( vf );
  188. }
  189. }
  190. // Add first position fo the list to close the path
  191. if( lastV != contournPoints[0] )
  192. contournPoints.push_back( contournPoints[0] );
  193. AddToMiddleContourns( contournPoints, zBot, zTop, aInvertFaceDirection, aThroughHoles );
  194. }
  195. void TRIANGLE_DISPLAY_LIST::AddToMiddleContourns( const SHAPE_POLY_SET& aPolySet, float zBot,
  196. float zTop, double aBiuTo3Du,
  197. bool aInvertFaceDirection,
  198. const BVH_CONTAINER_2D* aThroughHoles )
  199. {
  200. if( aPolySet.OutlineCount() == 0 )
  201. return;
  202. // Calculate an estimation of points to reserve
  203. unsigned int nrContournPointsToReserve = 0;
  204. for( int i = 0; i < aPolySet.OutlineCount(); ++i )
  205. {
  206. const SHAPE_LINE_CHAIN& pathOutline = aPolySet.COutline( i );
  207. nrContournPointsToReserve += pathOutline.PointCount();
  208. for( int h = 0; h < aPolySet.HoleCount( i ); ++h )
  209. {
  210. const SHAPE_LINE_CHAIN& hole = aPolySet.CHole( i, h );
  211. nrContournPointsToReserve += hole.PointCount();
  212. }
  213. }
  214. // Request to reserve more space
  215. m_layer_middle_contourns_quads->Reserve_More( nrContournPointsToReserve * 2, true );
  216. for( int i = 0; i < aPolySet.OutlineCount(); i++ )
  217. {
  218. // Add outline
  219. const SHAPE_LINE_CHAIN& pathOutline = aPolySet.COutline( i );
  220. AddToMiddleContourns( pathOutline, zBot, zTop, aBiuTo3Du, aInvertFaceDirection,
  221. aThroughHoles );
  222. // Add holes for this outline
  223. for( int h = 0; h < aPolySet.HoleCount( i ); ++h )
  224. {
  225. const SHAPE_LINE_CHAIN& hole = aPolySet.CHole( i, h );
  226. AddToMiddleContourns( hole, zBot, zTop, aBiuTo3Du, aInvertFaceDirection,
  227. aThroughHoles );
  228. }
  229. }
  230. }
  231. OPENGL_RENDER_LIST::OPENGL_RENDER_LIST( const TRIANGLE_DISPLAY_LIST& aLayerTriangles,
  232. GLuint aTextureIndexForSegEnds,
  233. float aZBot, float aZTop )
  234. {
  235. m_zBot = aZBot;
  236. m_zTop = aZTop;
  237. m_layer_top_segment_ends = 0;
  238. m_layer_top_triangles = 0;
  239. m_layer_middle_contourns_quads = 0;
  240. m_layer_bot_triangles = 0;
  241. m_layer_bot_segment_ends = 0;
  242. if( aTextureIndexForSegEnds )
  243. {
  244. wxASSERT( glIsTexture( aTextureIndexForSegEnds ) );
  245. if( glIsTexture( aTextureIndexForSegEnds ) )
  246. {
  247. m_layer_top_segment_ends =
  248. generate_top_or_bot_seg_ends( aLayerTriangles.m_layer_top_segment_ends,
  249. true, aTextureIndexForSegEnds );
  250. m_layer_bot_segment_ends =
  251. generate_top_or_bot_seg_ends( aLayerTriangles.m_layer_bot_segment_ends,
  252. false, aTextureIndexForSegEnds );
  253. }
  254. }
  255. m_layer_top_triangles = generate_top_or_bot_triangles( aLayerTriangles.m_layer_top_triangles,
  256. true );
  257. m_layer_bot_triangles = generate_top_or_bot_triangles( aLayerTriangles.m_layer_bot_triangles,
  258. false );
  259. if( aLayerTriangles.m_layer_middle_contourns_quads->GetVertexSize() > 0 )
  260. {
  261. m_layer_middle_contourns_quads =
  262. generate_middle_triangles( aLayerTriangles.m_layer_middle_contourns_quads );
  263. }
  264. m_draw_it_transparent = false;
  265. m_haveTransformation = false;
  266. m_zPositionTransformation = 0.0f;
  267. m_zScaleTransformation = 0.0f;
  268. }
  269. OPENGL_RENDER_LIST::~OPENGL_RENDER_LIST()
  270. {
  271. if( glIsList( m_layer_top_segment_ends ) )
  272. glDeleteLists( m_layer_top_segment_ends, 1 );
  273. if( glIsList( m_layer_top_triangles ) )
  274. glDeleteLists( m_layer_top_triangles, 1 );
  275. if( glIsList( m_layer_middle_contourns_quads ) )
  276. glDeleteLists( m_layer_middle_contourns_quads, 1 );
  277. if( glIsList( m_layer_bot_triangles ) )
  278. glDeleteLists( m_layer_bot_triangles, 1 );
  279. if( glIsList( m_layer_bot_segment_ends ) )
  280. glDeleteLists( m_layer_bot_segment_ends, 1 );
  281. m_layer_top_segment_ends = 0;
  282. m_layer_top_triangles = 0;
  283. m_layer_middle_contourns_quads = 0;
  284. m_layer_bot_triangles = 0;
  285. m_layer_bot_segment_ends = 0;
  286. }
  287. void OPENGL_RENDER_LIST::DrawTopAndMiddle() const
  288. {
  289. beginTransformation();
  290. if( glIsList( m_layer_middle_contourns_quads ) )
  291. glCallList( m_layer_middle_contourns_quads );
  292. if( glIsList( m_layer_top_triangles ) )
  293. glCallList( m_layer_top_triangles );
  294. if( glIsList( m_layer_top_segment_ends ) )
  295. glCallList( m_layer_top_segment_ends );
  296. endTransformation();
  297. }
  298. void OPENGL_RENDER_LIST::DrawBotAndMiddle() const
  299. {
  300. beginTransformation();
  301. if( glIsList( m_layer_middle_contourns_quads ) )
  302. glCallList( m_layer_middle_contourns_quads );
  303. if( glIsList( m_layer_bot_triangles ) )
  304. glCallList( m_layer_bot_triangles );
  305. if( glIsList( m_layer_bot_segment_ends ) )
  306. glCallList( m_layer_bot_segment_ends );
  307. endTransformation();
  308. }
  309. void OPENGL_RENDER_LIST::DrawTop() const
  310. {
  311. beginTransformation();
  312. if( glIsList( m_layer_top_triangles ) )
  313. glCallList( m_layer_top_triangles );
  314. if( glIsList( m_layer_top_segment_ends ) )
  315. glCallList( m_layer_top_segment_ends );
  316. endTransformation();
  317. }
  318. void OPENGL_RENDER_LIST::DrawBot() const
  319. {
  320. beginTransformation();
  321. if( glIsList( m_layer_bot_triangles ) )
  322. glCallList( m_layer_bot_triangles );
  323. if( glIsList( m_layer_bot_segment_ends ) )
  324. glCallList( m_layer_bot_segment_ends );
  325. endTransformation();
  326. }
  327. void OPENGL_RENDER_LIST::DrawMiddle() const
  328. {
  329. beginTransformation();
  330. if( glIsList( m_layer_middle_contourns_quads ) )
  331. glCallList( m_layer_middle_contourns_quads );
  332. endTransformation();
  333. }
  334. void OPENGL_RENDER_LIST::DrawAll( bool aDrawMiddle ) const
  335. {
  336. beginTransformation();
  337. if( aDrawMiddle )
  338. if( glIsList( m_layer_middle_contourns_quads ) )
  339. glCallList( m_layer_middle_contourns_quads );
  340. if( glIsList( m_layer_top_triangles ) )
  341. glCallList( m_layer_top_triangles );
  342. if( glIsList( m_layer_bot_triangles ) )
  343. glCallList( m_layer_bot_triangles );
  344. if( glIsList( m_layer_top_segment_ends ) )
  345. glCallList( m_layer_top_segment_ends );
  346. if( glIsList( m_layer_bot_segment_ends ) )
  347. glCallList( m_layer_bot_segment_ends );
  348. endTransformation();
  349. }
  350. void OPENGL_RENDER_LIST::DrawAllCameraCulled( float zCameraPos, bool aDrawMiddle ) const
  351. {
  352. zCameraPos = m_haveTransformation
  353. ? ( ( zCameraPos - m_zPositionTransformation ) / m_zScaleTransformation )
  354. : zCameraPos;
  355. if( aDrawMiddle )
  356. DrawMiddle();
  357. if( zCameraPos > m_zTop )
  358. {
  359. DrawTop();
  360. }
  361. else
  362. {
  363. if( zCameraPos < m_zBot )
  364. {
  365. DrawBot();
  366. }
  367. else
  368. {
  369. // If camera is in the middle dont draw it.
  370. }
  371. }
  372. }
  373. void OPENGL_RENDER_LIST::DrawAllCameraCulledSubtractLayer( bool aDrawMiddle,
  374. const OPENGL_RENDER_LIST* aLayerToSubtractA,
  375. const OPENGL_RENDER_LIST* aLayerToSubtractB,
  376. const OPENGL_RENDER_LIST* aLayerToSubtractC,
  377. const OPENGL_RENDER_LIST* aLayerToSubtractD ) const
  378. {
  379. glClearStencil( 0x00 );
  380. glClear( GL_STENCIL_BUFFER_BIT );
  381. glEnable( GL_CULL_FACE );
  382. glCullFace( GL_BACK );
  383. glDisable( GL_DEPTH_TEST );
  384. glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
  385. glDepthMask( GL_FALSE );
  386. glEnable( GL_STENCIL_TEST );
  387. glStencilFunc( GL_ALWAYS, 1, 0 );
  388. glStencilOp( GL_KEEP, GL_KEEP, GL_REPLACE );
  389. if( aLayerToSubtractA )
  390. aLayerToSubtractA->DrawBot();
  391. if( aLayerToSubtractB )
  392. aLayerToSubtractB->DrawBot();
  393. if( aLayerToSubtractC )
  394. aLayerToSubtractC->DrawBot();
  395. if( aLayerToSubtractD )
  396. aLayerToSubtractD->DrawBot();
  397. glEnable(GL_DEPTH_TEST);
  398. glDepthMask(GL_TRUE);
  399. glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
  400. glStencilFunc( GL_EQUAL, 0, 1 );
  401. glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
  402. DrawBot();
  403. glDisable( GL_DEPTH_TEST );
  404. glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
  405. glDepthMask( GL_FALSE );
  406. glEnable( GL_STENCIL_TEST );
  407. glStencilFunc( GL_ALWAYS, 2, 0 );
  408. glStencilOp( GL_KEEP, GL_KEEP, GL_REPLACE );
  409. if( aLayerToSubtractA )
  410. aLayerToSubtractA->DrawTop();
  411. if( aLayerToSubtractB )
  412. aLayerToSubtractB->DrawTop();
  413. if( aLayerToSubtractC )
  414. aLayerToSubtractC->DrawTop();
  415. if( aLayerToSubtractD )
  416. aLayerToSubtractD->DrawTop();
  417. glEnable(GL_DEPTH_TEST);
  418. glDepthMask(GL_TRUE);
  419. glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
  420. glStencilFunc( GL_NOTEQUAL, 2, 0x03 );
  421. glStencilOp( GL_KEEP, GL_KEEP, GL_INCR );
  422. DrawTop();
  423. if( aDrawMiddle )
  424. DrawMiddle();
  425. glLightModeli( GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE );
  426. glCullFace( GL_FRONT );
  427. glStencilFunc( GL_GEQUAL, 3, 0x03 );
  428. glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
  429. glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
  430. if( aDrawMiddle )
  431. {
  432. if( aLayerToSubtractA )
  433. aLayerToSubtractA->DrawMiddle();
  434. }
  435. glLightModeli( GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE );
  436. glCullFace( GL_BACK );
  437. glDisable( GL_STENCIL_TEST );
  438. }
  439. void OPENGL_RENDER_LIST::ApplyScalePosition( float aZposition, float aZscale )
  440. {
  441. wxCHECK2( aZscale > FLT_EPSILON, aZscale = FLT_EPSILON + 1 );
  442. m_zPositionTransformation = aZposition;
  443. m_zScaleTransformation = aZscale;
  444. m_haveTransformation = true;
  445. }
  446. void OPENGL_RENDER_LIST::SetItIsTransparent( bool aSetTransparent )
  447. {
  448. m_draw_it_transparent = aSetTransparent;
  449. }
  450. GLuint OPENGL_RENDER_LIST::generate_top_or_bot_seg_ends(
  451. const TRIANGLE_LIST* aTriangleContainer, bool aIsNormalUp, GLuint aTextureId ) const
  452. {
  453. wxASSERT( aTriangleContainer != nullptr );
  454. wxASSERT( ( aTriangleContainer->GetVertexSize() % 3 ) == 0 );
  455. // Top and Bot dont have normals array stored in container
  456. wxASSERT( aTriangleContainer->GetNormalsSize() == 0 );
  457. if( ( aTriangleContainer->GetVertexSize() > 0 )
  458. && ( ( aTriangleContainer->GetVertexSize() % 3 ) == 0 ) )
  459. {
  460. GLuint listIdx = glGenLists( 1 );
  461. if( glIsList( listIdx ) )
  462. {
  463. // Prepare an array of UV text coordinates
  464. SFVEC2F* uvArray = new SFVEC2F[aTriangleContainer->GetVertexSize()];
  465. for( unsigned int i = 0; i < aTriangleContainer->GetVertexSize(); i += 3 )
  466. {
  467. uvArray[i + 0] = SFVEC2F( 1.0f, 0.0f );
  468. uvArray[i + 1] = SFVEC2F( 0.0f, 1.0f );
  469. uvArray[i + 2] = SFVEC2F( 0.0f, 0.0f );
  470. }
  471. glEnableClientState( GL_TEXTURE_COORD_ARRAY );
  472. glDisableClientState( GL_COLOR_ARRAY );
  473. glDisableClientState( GL_NORMAL_ARRAY );
  474. glEnableClientState( GL_VERTEX_ARRAY );
  475. glVertexPointer( 3, GL_FLOAT, 0, aTriangleContainer->GetVertexPointer() );
  476. glTexCoordPointer( 2, GL_FLOAT, 0, uvArray );
  477. glNewList( listIdx, GL_COMPILE );
  478. glDisable( GL_COLOR_MATERIAL );
  479. glEnable( GL_TEXTURE_2D );
  480. glBindTexture( GL_TEXTURE_2D, aTextureId );
  481. glAlphaFunc( GL_GREATER, 0.2f );
  482. glEnable( GL_ALPHA_TEST );
  483. glNormal3f( 0.0f, 0.0f, aIsNormalUp?1.0f:-1.0f );
  484. glDrawArrays( GL_TRIANGLES, 0, aTriangleContainer->GetVertexSize() );
  485. glBindTexture( GL_TEXTURE_2D, 0 );
  486. glDisable( GL_TEXTURE_2D );
  487. glDisable( GL_ALPHA_TEST );
  488. glDisable( GL_BLEND );
  489. glEndList();
  490. glDisableClientState( GL_VERTEX_ARRAY );
  491. glDisableClientState( GL_TEXTURE_COORD_ARRAY );
  492. delete [] uvArray;
  493. return listIdx;
  494. }
  495. }
  496. return 0;
  497. }
  498. GLuint OPENGL_RENDER_LIST::generate_top_or_bot_triangles( const TRIANGLE_LIST* aTriangleContainer,
  499. bool aIsNormalUp ) const
  500. {
  501. wxASSERT( aTriangleContainer != nullptr );
  502. wxASSERT( ( aTriangleContainer->GetVertexSize() % 3 ) == 0 );
  503. // Top and Bot dont have normals array stored in container
  504. wxASSERT( aTriangleContainer->GetNormalsSize() == 0 );
  505. if( ( aTriangleContainer->GetVertexSize() > 0 )
  506. && ( ( aTriangleContainer->GetVertexSize() % 3 ) == 0 ) )
  507. {
  508. const GLuint listIdx = glGenLists( 1 );
  509. if( glIsList( listIdx ) )
  510. {
  511. glDisableClientState( GL_TEXTURE_COORD_ARRAY );
  512. glDisableClientState( GL_COLOR_ARRAY );
  513. glDisableClientState( GL_NORMAL_ARRAY );
  514. glEnableClientState( GL_VERTEX_ARRAY );
  515. glVertexPointer( 3, GL_FLOAT, 0, aTriangleContainer->GetVertexPointer() );
  516. glNewList( listIdx, GL_COMPILE );
  517. setBlendfunction();
  518. glNormal3f( 0.0f, 0.0f, aIsNormalUp?1.0f:-1.0f );
  519. glDrawArrays( GL_TRIANGLES, 0, aTriangleContainer->GetVertexSize() );
  520. glDisable( GL_BLEND );
  521. glEndList();
  522. glDisableClientState( GL_VERTEX_ARRAY );
  523. return listIdx;
  524. }
  525. }
  526. return 0;
  527. }
  528. GLuint OPENGL_RENDER_LIST::generate_middle_triangles(
  529. const TRIANGLE_LIST* aTriangleContainer ) const
  530. {
  531. wxASSERT( aTriangleContainer != nullptr );
  532. // We expect that it is a multiple of 3 vertex
  533. wxASSERT( ( aTriangleContainer->GetVertexSize() % 3 ) == 0 );
  534. // We expect that it is a multiple of 6 vertex (because we expect to add quads)
  535. wxASSERT( (aTriangleContainer->GetVertexSize() % 6 ) == 0 );
  536. // We expect that there are normals with same size as vertex
  537. wxASSERT( aTriangleContainer->GetNormalsSize() == aTriangleContainer->GetVertexSize() );
  538. if( ( aTriangleContainer->GetVertexSize() > 0 )
  539. && ( ( aTriangleContainer->GetVertexSize() % 3 ) == 0 )
  540. && ( ( aTriangleContainer->GetVertexSize() % 6 ) == 0 )
  541. && ( aTriangleContainer->GetNormalsSize() == aTriangleContainer->GetVertexSize() ) )
  542. {
  543. const GLuint listIdx = glGenLists( 1 );
  544. if( glIsList( listIdx ) )
  545. {
  546. glDisableClientState( GL_TEXTURE_COORD_ARRAY );
  547. glDisableClientState( GL_COLOR_ARRAY );
  548. glEnableClientState( GL_NORMAL_ARRAY );
  549. glEnableClientState( GL_VERTEX_ARRAY );
  550. glVertexPointer( 3, GL_FLOAT, 0, aTriangleContainer->GetVertexPointer() );
  551. glNormalPointer( GL_FLOAT, 0, aTriangleContainer->GetNormalsPointer() );
  552. glNewList( listIdx, GL_COMPILE );
  553. setBlendfunction();
  554. glDrawArrays( GL_TRIANGLES, 0, aTriangleContainer->GetVertexSize() );
  555. glDisable( GL_BLEND );
  556. glEndList();
  557. glDisableClientState( GL_VERTEX_ARRAY );
  558. glDisableClientState( GL_NORMAL_ARRAY );
  559. return listIdx;
  560. }
  561. }
  562. return 0;
  563. }
  564. void OPENGL_RENDER_LIST::endTransformation() const
  565. {
  566. if( m_haveTransformation )
  567. {
  568. glPopMatrix();
  569. }
  570. }
  571. void OPENGL_RENDER_LIST::setBlendfunction() const
  572. {
  573. glEnable( GL_BLEND );
  574. glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
  575. }
  576. void OPENGL_RENDER_LIST::beginTransformation() const
  577. {
  578. if( m_haveTransformation )
  579. {
  580. glPushMatrix();
  581. glTranslatef( 0.0f, 0.0f, m_zPositionTransformation );
  582. glScalef( 1.0f, 1.0f, m_zScaleTransformation );
  583. }
  584. }