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