0023022: This is desirable to access OpenGl extensions and core API (1.2+) in one...
[occt.git] / src / OpenGl / OpenGl_Polygon.cxx
CommitLineData
2166f0fa
SK
1// File: OpenGl_Polygon.cxx
2// Created: 13 July 2011
3// Author: Sergey ZERCHANINOV
4// Copyright: OPEN CASCADE 2011
5
5f8b738e 6#include <OpenGl_GlCore11.hxx>
2166f0fa
SK
7
8#include <OpenGl_Polygon.hxx>
9
2166f0fa
SK
10#include <OpenGl_telem_util.hxx>
11#include <OpenGl_TextureBox.hxx>
12#include <OpenGl_Memory.hxx>
13
14#include <OpenGl_AspectFace.hxx>
15#include <OpenGl_Structure.hxx>
16
17#include <GL/glu.h>
18
19#if (defined(_WIN32) || defined(__WIN32__))
20 #define STATIC
21#else
22 #define STATIC static
23#endif
24
25struct EXTRA_VERTEX
26{
27 GLfloat vert[3];
28 int ind;
1c35b92f 29 DEFINE_STANDARD_ALLOC
2166f0fa
SK
30};
31typedef EXTRA_VERTEX* extra_vertex;
32
33struct SEQ_
34{
35 Tint ts_num, ts_alloc;
36 void **tmesh_sequence;
37 GLenum triangle_type; /* FSXXX OPTI */
1c35b92f 38 DEFINE_STANDARD_ALLOC
2166f0fa
SK
39};
40
41struct OPENGL_DISPLAY_PGN
42{
43 Tint num_of_seq;
44 Tint num_alloc;
45 SEQ_ *seq;
1c35b92f 46 DEFINE_STANDARD_ALLOC
2166f0fa
SK
47};
48
49static void bgntriangulate( const TEL_POLYGON_DATA *, void (APIENTRY*)() );
50static void endtriangulate(void);
51
52#ifndef GLU_VERSION_1_2
53 #define GLUtesselator GLUtriangulatorObj
54 void gluTessBeginContour();
55 void gluTessBeginPolygon();
56 void gluTessEndPolygon();
57 void gluTessEndContour();
58 #define GLU_TESS_BEGIN 100100
59 #define GLU_TESS_VERTEX 100101
60 #define GLU_TESS_END 100102
61 #define GLU_TESS_ERROR 100103
62 #define GLU_TESS_COMBINE 100105
63#endif
64
65/*----------------------------------------------------------------------*/
66
67void OpenGl_Polygon::draw_polygon (const Handle(OpenGl_Workspace) &AWorkspace, Tint front_lighting_model) const
68{
69 Tint i;
70
71 tel_point ptr;
72 tel_point pvn;
73 tel_colour pfc, pvc;
74 tel_texture_coord pvt;
75
76 pfc = myData.fcolour;
77 pvc = myData.vcolours;
78 pvn = myData.vnormals;
79 pvt = myData.vtexturecoord;
80
81 if ( AWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT )
82 pvc = pfc = NULL;
83
84 ptr = myData.vertices;
85 if ( pfc )
86 glColor3fv( pfc->rgb );
87 if ( front_lighting_model )
88 glNormal3fv( myData.fnormal.xyz );
89
90 if( myData.reverse_order ) glFrontFace( GL_CW );
91
92 if (myData.num_vertices == 3) glBegin(GL_TRIANGLES);
93 else if(myData.num_vertices == 4) glBegin(GL_QUADS);
94 else glBegin(GL_POLYGON);
95 if( front_lighting_model )
96 {
97 if( pvn )
98 {
99 if (pvt && (AWorkspace->NamedStatus & OPENGL_NS_FORBIDSETTEX) == 0)
100 for( i=0; i<myData.num_vertices; i++, ptr++ )
101 {
102 glNormal3fv( pvn[i].xyz );
103 glTexCoord2fv( pvt[i].xy );
104 glVertex3fv( ptr->xyz );
105 }
106 else
107 for( i=0; i<myData.num_vertices; i++, ptr++ )
108 {
109 glNormal3fv( pvn[i].xyz );
110 glVertex3fv( ptr->xyz );
111 }
112 }
113 else
114 {
115 for( i=0; i<myData.num_vertices; i++, ptr++ )
116 {
117 glVertex3fv( ptr->xyz );
118 }
119 }
120 }
121 else
122 {
123 if( pvc )
124 {
125 for( i=0; i<myData.num_vertices; i++, ptr++ )
126 {
127 glColor3fv( pvc[i].rgb );
128 glVertex3fv( ptr->xyz );
129 }
130 }
131 else
132 {
133 for( i=0; i<myData.num_vertices; i++, ptr++ )
134 {
135 glVertex3fv( ptr->xyz );
136 }
137 }
138 }
139 glEnd();
140 if( myData.reverse_order ) glFrontFace( GL_CCW );
141
142}
143
144/*----------------------------------------------------------------------*/
145
146/* JWR - allow varying the size */
147
148#define INCREMENT 8
149
150static int seq_increment = INCREMENT;
151
152static const TEL_POLYGON_DATA *DaTa;
153static GLUtesselator *tripak = 0;
154
155STATIC void APIENTRY
156out_bgntmesh( GLenum triangle_type )
157{
158 OPENGL_DISPLAY_PGN *dis = DaTa->dsply;
159
160 dis->num_of_seq++;
161 if( dis->num_alloc < dis->num_of_seq )
162 {
163 dis->num_alloc += seq_increment;
164
165 if( dis->seq == 0 )
166 {
167 dis->seq = new SEQ_[dis->num_alloc];
168 }
169 else
170 {
171#if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x530)
172 dis->seq = (SEQ_*)realloc( dis->seq, dis->num_alloc*sizeof(SEQ_) );
173#else
174 dis->seq = cmn_resizemem<SEQ_>( dis->seq, dis->num_alloc );
175#endif
176 }
177 }
178 dis->seq[ dis->num_of_seq - 1 ].ts_num = 0;
179 dis->seq[ dis->num_of_seq - 1 ].ts_alloc = 0;
180 dis->seq[ dis->num_of_seq - 1 ].tmesh_sequence = 0;
181
182#ifdef JWR_DEC_TRIFAN_BUG
183 dis->seq[ dis->num_of_seq - 1 ].triangle_type = GL_POLYGON;
184 glBegin(GL_POLYGON);
185#else
186 dis->seq[ dis->num_of_seq - 1 ].triangle_type = triangle_type;
187 glBegin(triangle_type);
188#endif
189}
190
191/*----------------------------------------------------------------------*/
192
193STATIC void APIENTRY
194out_vert1( void *data )
195{
196 SEQ_ *s = &( DaTa->dsply->seq[ DaTa->dsply->num_of_seq - 1 ] );
197
198 s->ts_num++;
199 if( s->ts_alloc < s->ts_num )
200 {
201 s->ts_alloc += seq_increment;
202
203 if( s->tmesh_sequence == 0 )
204 {
205 s->tmesh_sequence = new void*[s->ts_alloc];
206 }
207 else
208 {
209#if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x530)
210 s->tmesh_sequence = (void**)realloc( s->tmesh_sequence, s->ts_alloc*sizeof(void*));
211#else
212 s->tmesh_sequence = cmn_resizemem<void*>( s->tmesh_sequence, s->ts_alloc);
213#endif
214 }
215 }
216 s->tmesh_sequence[ s->ts_num - 1 ] = data;
217
218
219 if ( data < (void *)0xffff ) {
220 long a = (long)data;
221
222 glVertex3fv( DaTa->vertices[a].xyz );
223 }
224 else {
225 extra_vertex b = (extra_vertex) data;
226
227 glVertex3fv( b->vert );
228 }
229
230}
231
232/*----------------------------------------------------------------------*/
233
234STATIC void APIENTRY
235out_vert2( void *data )
236{
237 SEQ_ *s = &( DaTa->dsply->seq[ DaTa->dsply->num_of_seq - 1 ] );
238
239 s->ts_num++;
240 if( s->ts_alloc < s->ts_num )
241 {
242 s->ts_alloc += seq_increment;
243
244 if( s->tmesh_sequence == 0 )
245 {
246 s->tmesh_sequence = new void*[s->ts_alloc];
247 }
248 else
249 {
250#if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x530)
251 s->tmesh_sequence = (void**)( s->tmesh_sequence, s->ts_alloc*sizeof(void*) );
252#else
253 s->tmesh_sequence = cmn_resizemem<void*>( s->tmesh_sequence, s->ts_alloc );
254#endif
255 }
256 }
257 s->tmesh_sequence[ s->ts_num - 1 ] = data;
258
259 if ( data < (void *)0xffff ) {
260 long a = (long)data;
261
262 glColor3fv( DaTa->vcolours[a].rgb );
263 glVertex3fv( DaTa->vertices[a].xyz );
264 }
265 else {
266 extra_vertex b = (extra_vertex) data;
267
268 glColor3fv( DaTa->vcolours[(b->ind)].rgb );
269 glVertex3fv( b->vert );
270 }
271}
272
273/*----------------------------------------------------------------------*/
274
275STATIC void APIENTRY
276out_vert3( void *data )
277{
278 SEQ_ *s = &( DaTa->dsply->seq[ DaTa->dsply->num_of_seq - 1 ] );
279
280 s->ts_num++;
281 if( s->ts_alloc < s->ts_num )
282 {
283 s->ts_alloc += seq_increment;
284
285 if( s->tmesh_sequence == 0 )
286 {
287 s->tmesh_sequence = new void*[s->ts_alloc];
288 }
289 else
290 {
291#if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x530)
292 s->tmesh_sequence = (void**)realloc( s->tmesh_sequence, s->ts_alloc*sizeof(void*) );
293#else
294 s->tmesh_sequence = cmn_resizemem<void*>( s->tmesh_sequence, s->ts_alloc );
295#endif
296 }
297 }
298 s->tmesh_sequence[ s->ts_num - 1 ] = data;
299
300 if ( data <= (void *)0xffff ) {
301 long a = (long)data;
302
303 glNormal3fv( DaTa->vnormals[a].xyz );
304 glVertex3fv( DaTa->vertices[a].xyz);
305 }
306 else {
307 extra_vertex b = (extra_vertex) data;
308
309 glNormal3fv( DaTa->vnormals[(b->ind)].xyz );
310 glVertex3fv( b->vert );
311 }
312}
313
314/*----------------------------------------------------------------------*/
315
316STATIC void APIENTRY
317mycombine( GLdouble coords[3], int *data, GLfloat w[4], void **dataout)
318{
319 extra_vertex new_vertex = (extra_vertex) malloc(sizeof(EXTRA_VERTEX));
320
321 new_vertex->vert[0] = ( float )coords[0];
322 new_vertex->vert[1] = ( float )coords[1];
323 new_vertex->vert[2] = ( float )coords[2];
324 new_vertex->ind = *data;
325 *dataout = new_vertex;
326}
327
328/*----------------------------------------------------------------------*/
329
330STATIC void APIENTRY
331out_endtmesh( void )
332{
333 glEnd();
334}
335
336/*----------------------------------------------------------------------*/
337
338STATIC void APIENTRY
339out_error( GLenum error )
340{
341 printf( "POLYGON : %s\n", (char *) gluErrorString(error) );
342}
343
344/*----------------------------------------------------------------------*/
345
346static void
347bgntriangulate(const TEL_POLYGON_DATA *d, void ( APIENTRY * out_ver)() )
348{
349 DaTa = d;
350
351 tripak = gluNewTess();
352
353#if defined(linux) && !defined(NOGLUfuncptr)
354 gluTessCallback( tripak, GLU_TESS_BEGIN, (_GLUfuncptr)(out_bgntmesh) );
355 gluTessCallback( tripak, GLU_TESS_VERTEX, out_ver );
356 gluTessCallback( tripak, GLU_TESS_END, out_endtmesh );
357 gluTessCallback( tripak, GLU_TESS_ERROR, (_GLUfuncptr)(out_error) );
358 gluTessCallback( tripak, GLU_TESS_COMBINE, (_GLUfuncptr)(mycombine) );
359#else
360 gluTessCallback( tripak, GLU_TESS_BEGIN, (void (APIENTRY*)())out_bgntmesh );
361 gluTessCallback( tripak, GLU_TESS_VERTEX, (void (APIENTRY*)())out_ver );
362 gluTessCallback( tripak, GLU_TESS_END, (void (APIENTRY*)())out_endtmesh );
363 gluTessCallback( tripak, GLU_TESS_ERROR, (void (APIENTRY*)())out_error );
364 gluTessCallback( tripak, GLU_TESS_COMBINE, (void (APIENTRY*)())mycombine );
365#endif
366}
367
368/*----------------------------------------------------------------------*/
369
370static void
371endtriangulate()
372{
373 DaTa = 0;
374 gluDeleteTess(tripak);
375}
376
377/*----------------------------------------------------------------------*/
378
379void OpenGl_Polygon::draw_polygon_concav (const Handle(OpenGl_Workspace) &AWorkspace, Tint front_lighting_model) const
380{
381 long i;
382
383 tel_point pvn;
384 tel_point ptr;
385 tel_colour pfc, pvc;
386 GLdouble xyz[3];
387
388 pfc = myData.fcolour;
389 pvc = myData.vcolours;
390 pvn = myData.vnormals;
391
392 if ( AWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT )
393 pvc = pfc = NULL;
394
395 ptr = myData.vertices;
396 DaTa = &myData;
397
398 if ( pfc )
399 glColor3fv( pfc->rgb );
400 if ( front_lighting_model )
401 glNormal3fv( myData.fnormal.xyz );
402
403 if( myData.reverse_order ) glFrontFace( GL_CW );
404
405 if( !myData.dsply )
406 {
407 if( front_lighting_model )
408 {
409 if( pvn )
410 {
411 bgntriangulate(&myData, (void (APIENTRY*)())out_vert3);
412 }
413 else
414 {
415 bgntriangulate(&myData, (void (APIENTRY*)())out_vert1);
416 }
417 }
418 else
419 {
420 if( pvc )
421 {
422 bgntriangulate(&myData, (void (APIENTRY*)())out_vert2);
423 }
424 else
425 {
426 bgntriangulate(&myData, (void (APIENTRY*)())out_vert1);
427 }
428 }
429 gluTessBeginPolygon( tripak, NULL );
430 gluTessBeginContour( tripak);
431
432 for( i=0; i<myData.num_vertices; i++, ptr++ )
433 {
434 xyz[0] = ptr->xyz[0];
435 xyz[1] = ptr->xyz[1];
436 xyz[2] = ptr->xyz[2];
437#ifndef WNT
438 gluTessVertex( tripak, xyz,(void * ) i );
439#else
440 {
441 double v[ 3 ] = {ptr -> xyz[ 0 ], ptr -> xyz[ 1 ], ptr -> xyz[ 2 ]};
442 gluTessVertex ( tripak, v, ( void* )i );
443 }
444#endif /* WNT */
445 }
446 gluTessEndContour( tripak );
447 gluTessEndPolygon( tripak );
448 endtriangulate();
449 }
450 else
451 {
452 if( front_lighting_model )
453 {
454 draw_tmesh( pvn? 3 : 1 );
455 }
456 else
457 {
458 draw_tmesh( pvc? 2 : 1 );
459 }
460 }
461
462 if( myData.reverse_order ) glFrontFace( GL_CCW );
463}
464
465/*----------------------------------------------------------------------*/
466
467void OpenGl_Polygon::draw_edges (const TEL_COLOUR *edge_colour, const Aspect_InteriorStyle interior_style, const Handle(OpenGl_Workspace) &AWorkspace) const
468{
469 const OpenGl_AspectFace *aspect_face = AWorkspace->AspectFace( Standard_True );
470
471 if ( interior_style != Aspect_IS_HIDDENLINE && aspect_face->Context().Edge == TOff )
472 return;
473
474 glDisable(GL_LIGHTING);
475 const GLboolean texture_on = IsTextureEnabled();
476 if (texture_on) DisableTexture();
477
478 // Setup line aspect
479 const OpenGl_AspectLine *aspect_line_old = AWorkspace->SetAspectLine( aspect_face->AspectEdge() );
480 AWorkspace->AspectLine( Standard_True );
481
482 Tint i;
483 tel_point ptr = myData.vertices;
484
485 glColor3fv( edge_colour->rgb );
486
487 glBegin(GL_LINE_LOOP);
488 for( i=0; i<myData.num_vertices; i++, ptr++ )
489 {
490 glVertex3fv( ptr->xyz );
491 }
492 glEnd();
493
494 // Restore line context
495 AWorkspace->SetAspectLine( aspect_line_old );
496
497 if (texture_on) EnableTexture();
498}
499
500/*----------------------------------------------------------------------*/
501
502void OpenGl_Polygon::draw_tmesh ( Tint v ) const
503{
504 Tint i, j, k;
505 SEQ_ *s;
506 extra_vertex b;
507
508 OPENGL_DISPLAY_PGN *dis = myData.dsply;
509 for( i = 0; i < dis->num_of_seq; i++ )
510 {
511 s = &(dis->seq[i]);
512
513 glBegin(s->triangle_type);
514 switch( v )
515 {
516 case 1:
517 {
518 for( j = 0, k = 0; j < s->ts_num; j++ )
519 {
520 if ( s->tmesh_sequence[j] < (void *)0xffff )
521 glVertex3fv( myData.vertices[ (long)s->tmesh_sequence[ j ] ].xyz );
522 else {
523 extra_vertex b = (extra_vertex)s->tmesh_sequence[j];
524 glVertex3fv( b->vert );
525 }
526
527 }
528 break;
529 }
530 case 2:
531 {
532 for( j = 0, k = 0; j < s->ts_num; j++ )
533 {
534 if ( s->tmesh_sequence[j] < (void *)0xffff ) {
535 glColor3fv( myData.vcolours[ (long) s->tmesh_sequence[ j ] ].rgb );
536 glVertex3fv( myData.vertices[ (long) s->tmesh_sequence[ j ] ].xyz );
537 } else {
538 b = (extra_vertex) s->tmesh_sequence[j];
539 glColor3fv( myData.vcolours[(b->ind)].rgb);
540 glVertex3fv( b->vert );
541 }
542 }
543 break;
544 }
545 case 3:
546 {
547 for( j = 0, k = 0; j < s->ts_num; j++ )
548 {
549 if ( s->tmesh_sequence[j] < (void *)0xffff ) {
550 glNormal3fv( myData.vnormals[ (long) s->tmesh_sequence[ j ] ].xyz);
551 glVertex3fv( myData.vertices[ (long) s->tmesh_sequence[ j ] ].xyz);
552 } else {
553 b = (extra_vertex) s->tmesh_sequence[j];
554 glNormal3fv( myData.vnormals[(b->ind)].xyz);
555 glVertex3fv( b->vert );
556 }
557 }
558 break;
559 }
560 }
561 glEnd();
562 }
563}
564
565/*----------------------------------------------------------------------*/
566
567OpenGl_Polygon::OpenGl_Polygon (const Graphic3d_Array1OfVertex& AListVertex,
568 const Graphic3d_TypeOfPolygon AType)
569{
570 const Standard_Integer nv = AListVertex.Length();
571
572 myData.num_vertices = nv;
573
574 myData.vertices = new TEL_POINT[nv];
575 memcpy( myData.vertices, &AListVertex(AListVertex.Lower()), nv*sizeof(TEL_POINT) );
576
577 myData.vertex_flag = TEL_VT_NONE;
578 myData.vnormals = NULL;
579
580 myData.vcolours = NULL;
581
582 myData.vtexturecoord = NULL;
583
584 myData.reverse_order = 0;
585
586 myData.facet_flag = TEL_FA_NONE;
587 TelGetPolygonNormal( myData.vertices, NULL, nv, myData.fnormal.xyz );
588
589 myData.fcolour = NULL;
590
591#if defined(__sgi) || defined(IRIX)
592 // Pb with tesselator on sgi
593 myData.shape_flag = TEL_SHAPE_CONVEX;
594#else
595 switch (AType)
596 {
597 case Graphic3d_TOP_UNKNOWN :
598 myData.shape_flag = TEL_SHAPE_UNKNOWN;
599 break;
600 case Graphic3d_TOP_COMPLEX :
601 myData.shape_flag = TEL_SHAPE_COMPLEX;
602 break;
603 case Graphic3d_TOP_CONCAVE :
604 myData.shape_flag = TEL_SHAPE_CONCAVE;
605 break;
606 //case Graphic3d_TOP_CONVEX :
607 default :
608 myData.shape_flag = TEL_SHAPE_CONVEX;
609 break;
610 }
611#endif
612
613 myData.dsply = new OPENGL_DISPLAY_PGN();
614 myData.dsply->num_of_seq = 0;
615 myData.dsply->num_alloc = 0;
616 myData.dsply->seq = NULL;
617}
618
619/*----------------------------------------------------------------------*/
620
621OpenGl_Polygon::~OpenGl_Polygon ()
622{
623 if( myData.fcolour )
624 delete myData.fcolour;
625 if( myData.vertices )
626 delete[] myData.vertices;
627 if( myData.vcolours )
628 delete[] myData.vcolours;
629 if( myData.vnormals )
630 delete[] myData.vnormals;
631 if ( myData.vtexturecoord )
632 delete myData.vtexturecoord;
633
634 if ( myData.dsply )
635 {
636 Tint i, j;
637
638 for( i = 0; i < myData.dsply->num_of_seq; i++ )
639 {
640 if(myData.dsply->seq[i].tmesh_sequence) {
641 for ( j = 0; j < myData.dsply->seq[i].ts_num ; j++ ) {
642 if ( myData.dsply->seq[i].tmesh_sequence[j] >= (void *)0xffff )
643 free(myData.dsply->seq[i].tmesh_sequence[j]);
644 }
645 }
646 delete[] myData.dsply->seq[i].tmesh_sequence;
647 }
648 delete[] myData.dsply->seq;
649 delete myData.dsply;
650 }
651}
652
653/*----------------------------------------------------------------------*/
654
655void OpenGl_Polygon::Render (const Handle(OpenGl_Workspace) &AWorkspace) const
656{
657 const OpenGl_AspectFace *aspect_face = AWorkspace->AspectFace( Standard_True );
658
659 Tint front_lighting_model = aspect_face->Context().IntFront.color_mask;
660 const Aspect_InteriorStyle interior_style = aspect_face->Context().InteriorStyle;
661 const TEL_COLOUR *interior_colour = &aspect_face->Context().IntFront.matcol;
662 const TEL_COLOUR *edge_colour = &aspect_face->AspectEdge()->Color();
663
664 // Use highlight colous
665 if ( AWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT )
666 {
667 edge_colour = interior_colour = AWorkspace->HighlightColor;
668 front_lighting_model = 0;
669 }
670
671 if( interior_style != Aspect_IS_EMPTY && AWorkspace->DegenerateModel < 2 )
672 {
673 if ( front_lighting_model )
674 glEnable(GL_LIGHTING);
675 else
676 glDisable(GL_LIGHTING);
677
678 glColor3fv( interior_colour->rgb );
679
680 if( myData.shape_flag != TEL_SHAPE_CONVEX )
681 draw_polygon_concav( AWorkspace, front_lighting_model );
682 else
683 draw_polygon( AWorkspace, front_lighting_model );
684 }
685
686 /* OCC11904 -- Temporarily disable environment mapping */
687 glPushAttrib(GL_ENABLE_BIT);
688 glDisable(GL_TEXTURE_1D);
689 glDisable(GL_TEXTURE_2D);
690
691 switch ( AWorkspace->DegenerateModel )
692 {
693 default:
694 draw_edges ( edge_colour, interior_style, AWorkspace );
695 break;
696 case 3: /* marker degeneration */
697 break;
698 }
699
700 glPopAttrib(); /* skt: GL_ENABLE_BIT*/
701}
702
703/*----------------------------------------------------------------------*/