cfbaca3e84adf931d59b551037f3cc1026dba325
[occt.git] / src / OpenGl / OpenGl_Polygon.cxx
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
26 struct EXTRA_VERTEX
27 {
28   GLfloat vert[3];
29   int ind;
30   DEFINE_STANDARD_ALLOC
31 };
32 typedef EXTRA_VERTEX* extra_vertex;
33
34 struct SEQ_
35 {
36   Tint ts_num, ts_alloc;
37   void **tmesh_sequence;
38   GLenum triangle_type; /* FSXXX OPTI */
39   DEFINE_STANDARD_ALLOC
40 };
41
42 struct OPENGL_DISPLAY_PGN
43 {
44   Tint num_of_seq;
45   Tint num_alloc;
46   SEQ_ *seq;
47   DEFINE_STANDARD_ALLOC
48 };
49
50 static void bgntriangulate( const TEL_POLYGON_DATA *, void (APIENTRY*)() );
51 static 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
68 void 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
151 static int seq_increment = INCREMENT;
152
153 static const TEL_POLYGON_DATA *DaTa;
154 static GLUtesselator *tripak = 0;
155
156 STATIC void APIENTRY
157 out_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
194 STATIC void APIENTRY
195 out_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
235 STATIC void APIENTRY
236 out_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
276 STATIC void APIENTRY
277 out_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
317 STATIC void APIENTRY
318 mycombine( 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
331 STATIC void APIENTRY
332 out_endtmesh( void )
333 {
334   glEnd();
335 }
336
337 /*----------------------------------------------------------------------*/
338
339 STATIC void APIENTRY
340 out_error( GLenum error )
341 {
342   printf( "POLYGON : %s\n", (char *) gluErrorString(error) );
343 }
344
345 /*----------------------------------------------------------------------*/
346
347 static void
348 bgntriangulate(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
371 static void
372 endtriangulate()
373 {
374   DaTa = 0;
375   gluDeleteTess(tripak);
376 }
377
378 /*----------------------------------------------------------------------*/
379
380 void 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
468 void 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
503 void 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
568 OpenGl_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
622 OpenGl_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
656 void 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 /*----------------------------------------------------------------------*/