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