OCC22108 Cutting plane unpredictable behaviour in V3d_View
[occt.git] / src / OpenGl / OpenGl_polygonholes.cxx
1 /***********************************************************************
2
3 FONCTION :
4 ----------
5 File OpenGl_polygonholes :
6
7
8 REMARQUES:
9 ---------- 
10
11
12 HISTORIQUE DES MODIFICATIONS   :
13 --------------------------------
14 xx-xx-xx : xxx ; Creation.
15 11-03-96 : FMN ; Correction warning compilation
16 01-04-96 : CAL ; Integration MINSK portage WNT
17 09-08-96 : FMN ; Suppression appel glMatrixMode() avant glGetFloatv()
18 21-10-96 : FMN ; Suppression LMC_COLOR fait dans OpenGl_execstruct.c
19 23-12-97 : FMN ; Suppression TelSetFrontFaceAttri et TelSetBackFaceAttri 
20 Suppression TelBackInteriorStyle, TelBackInteriorStyleIndex
21 et TelBackInteriorShadingMethod
22 03-03-98 : FMN ; Suppression variable externe TglWhetherPerspective 
23 08-03-01 : GG  ; BUC60823 Avoid crash in the normal computation method
24 on confuse point.
25
26 ************************************************************************/
27
28 /*----------------------------------------------------------------------*/
29 /*
30 * Includes
31 */ 
32
33
34 #include <OpenGl_tgl_all.hxx>
35
36 #include <stddef.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39
40 #include <OpenGl_cmn_varargs.hxx>
41 #include <OpenGl_Extension.hxx>
42 #include <OpenGl_telem_attri.hxx>
43 #include <OpenGl_tsm.hxx>
44 #include <OpenGl_telem.hxx>
45 #include <OpenGl_telem_util.hxx>
46 #include <OpenGl_telem_highlight.hxx>
47 #include <OpenGl_telem_inquire.hxx>
48 #include <OpenGl_telem_view.hxx>
49 #include <OpenGl_tgl_funcs.hxx>
50 #include <OpenGl_Memory.hxx>
51
52 #ifndef WNT
53 #if !defined(APIENTRY)
54 # define APIENTRY
55 #endif // APIENTRY
56 # define STATIC static
57 #else
58 # include <GL\GLU.H>
59 # define STATIC
60 typedef double GLUcoord;
61 #endif  /* WNT */
62
63
64 /*----------------------------------------------------------------------*/
65 /*
66 * Variables statiques
67 */ 
68
69 static  TStatus  PolygonHolesDisplay( TSM_ELEM_DATA, Tint, cmn_key* );
70 static  TStatus  PolygonHolesAdd( TSM_ELEM_DATA, Tint, cmn_key* );
71 static  TStatus  PolygonHolesDelete( TSM_ELEM_DATA, Tint, cmn_key* );
72 static  TStatus  PolygonHolesPrint( TSM_ELEM_DATA, Tint, cmn_key* );
73 static  TStatus  PolygonHolesInquire( TSM_ELEM_DATA, Tint, cmn_key* );
74
75 #if !defined(GLU_VERSION_1_2)
76 #define GLUtesselator GLUtriangulatorObj
77 void gluTessBeginContour();
78 void gluTessBeginPolygon();
79 void gluTessEndPolygon();
80 void gluTessEndContour();
81 #endif
82
83
84 /*----------------------------------------------------------------------*/
85 /*
86 * Typedef
87 */ 
88
89 struct EXTRA_VERTEX
90 {
91   GLfloat vert[3];
92   int ind;
93   IMPLEMENT_MEMORY_OPERATORS
94 };
95 typedef EXTRA_VERTEX* extra_vertex;
96
97 struct SEQ_
98 {
99   Tint ts_num, ts_alloc;
100   void **tmesh_sequence;
101   GLenum triangle_type; /* FSXXX OPTI */
102   IMPLEMENT_MEMORY_OPERATORS
103 };
104
105 struct DISPLAY_
106 {
107   Tint num_of_seq;
108   Tint num_alloc;
109   SEQ_ *seq;
110   IMPLEMENT_MEMORY_OPERATORS
111 };
112
113 struct TEL_POLYGON_HOLES_DATA
114 {
115   Tint       num_vertices;    /* Number of vertices */
116   Tint       facet_flag;      /* TEL_FA_NONE or TEL_FA_NORMAL */
117   Tint       vertex_flag;     /* TEL_VT_NONE or TEL_VT_NORMAL */
118   Tint       shape_flag;      /* TEL_SHAPE_UNKNOWN or TEL_SHAPE_COMPLEX or
119                               TEL_SHAPE_CONVEX  or TEL_SHAPE_CONCAVE */
120   TEL_POINT  fnormal;         /* Facet normal */
121   Tint       *edgevis;        /* edge visibility flags */
122   tel_colour fcolour;         /* Facet colour */
123   Tint       num_bounds;      /* number of bounds */
124   Tint       *bounds;         /* Array of length num_bounds */
125   tel_point  vertices;        /* Vertices */
126   tel_colour vcolours;        /* Vertex colour values */
127   tel_point  vnormals;        /* Vertex normals */
128   DISPLAY_   *display;        /* FSXXX plus utilise ? */
129   GLuint     triangle_dl1;  /* triangle display list 1 */
130   GLuint     triangle_dl2;  /* triangle display list 2 */
131   GLuint     triangle_dl3;  /* triangle display list 3 */
132 };
133 typedef TEL_POLYGON_HOLES_DATA* tel_polygon_holes_data;
134
135 static TEL_POLYGON_HOLES_DATA polygon_holes_defaults =
136 {
137   0,                 /* num_vertices */
138   TEL_FA_NONE,       /* facet_flag */
139   TEL_VT_NONE,       /* vertex_flag */
140   TEL_SHAPE_UNKNOWN, /* shape_flag */
141   {{ ( float )0.0, ( float )0.0, ( float )0.0 }}, /* fnormal */
142   0,                 /* edgevis */
143   0,                 /* fcolour */
144   0,                 /* num_bounds */
145   0,                 /* bounds */
146   0,                 /* vertices */
147   0,                 /* vcolours */
148   0,                 /* vnormals */
149   0,                 /* display */
150   0,       /* triangle_dl1 */
151   0,       /* triangle_dl2 */
152   0      /* triangle_dl3 */
153 };
154
155 static void bgntriangulate( tel_polygon_holes_data, void (APIENTRY*)() );
156 static void endtriangulate(void);
157 STATIC void APIENTRY out_vertex1( void* );
158 STATIC void APIENTRY out_vertex2( void* );
159 STATIC void APIENTRY out_vertex3( void* );
160 static void draw_tmesh( tel_polygon_holes_data, Tint );
161 static void draw_polygon_holes( tel_polygon_holes_data, Tint,
162                                Tint, Tint );
163 static void draw_edges( tel_polygon_holes_data, Tmatrix3, tel_colour, Tint,
164                        TelCullMode, Tint, Tint );
165
166 static  TStatus  (*MtdTbl[])( TSM_ELEM_DATA, Tint, cmn_key* ) =
167 {
168   PolygonHolesDisplay,             /* PickTraverse */
169     PolygonHolesDisplay,
170     PolygonHolesAdd,
171     PolygonHolesDelete,
172     PolygonHolesPrint,
173     PolygonHolesInquire
174 };
175
176
177 MtblPtr
178 TelPolygonHolesInitClass( TelType* el )
179 {
180   *el = TelPolygonHoles;
181   return MtdTbl;
182 }
183
184 static  TStatus
185 PolygonHolesAdd( TSM_ELEM_DATA d, Tint n, cmn_key *k )
186 {
187   Tint                   i, j, m;
188   tel_polygon_holes_data data;
189
190   for( i = 0; i < n; i++ )
191   {
192     if( k[i]->id == NUM_FACETS_ID )
193       break;
194   }
195   if( i == n )
196     return TFailure;
197
198   if( !(k[i]->data.ldata) )
199     return TFailure;
200
201   for( j = 0; j < n; j++ )
202   {
203     if( k[j]->id == BOUNDS_DATA_ID )
204       break;
205   }
206   if( j == n )
207     return TFailure;
208
209   data = new TEL_POLYGON_HOLES_DATA();
210   if( !data )
211     return TFailure;
212
213   /* load defaults */
214   memcpy( data, &polygon_holes_defaults, sizeof(TEL_POLYGON_HOLES_DATA) );
215
216   data->num_bounds = k[i]->data.ldata;
217   data->bounds = new Tint[data->num_bounds];
218   memcpy( data->bounds, k[j]->data.pdata, data->num_bounds*sizeof(Tint) );
219
220   for( m = 0, data->num_vertices = 0; m < data->num_bounds; m++ )
221     data->num_vertices += data->bounds[m];
222
223   for( i = 0; i < n; i++ )
224   {
225     if( k[i]->id == VERTICES_ID )
226       break;
227   }
228   if( i == n )
229     return TFailure;
230
231   if( !(k[i]->data.ldata) )
232     return TFailure;
233
234   data->vertices = new TEL_POINT[data->num_vertices];
235   memcpy( data->vertices, k[i]->data.pdata, data->num_vertices*sizeof(TEL_POINT) );
236
237   for( i = 0; i < n; i++ )
238   {
239     switch( k[i]->id )
240     {
241     case FNORMALS_ID:
242       data->facet_flag = TEL_FA_NORMAL;
243       memcpy( &data->fnormal, k[i]->data.pdata, sizeof(TEL_POINT) );
244       vecnrm( data->fnormal.xyz );
245       break;
246
247     case FACET_COLOUR_VALS_ID:
248       data->fcolour = new TEL_COLOUR();
249       memcpy( data->fcolour, k[i]->data.pdata, sizeof(TEL_COLOUR) );
250       break;
251
252     case EDGE_DATA_ID:
253       data->edgevis = new Tint[data->num_vertices];
254       memcpy( data->edgevis, k[i]->data.pdata, sizeof(Tint) );
255       break;
256
257     case VERTEX_COLOUR_VALS_ID:
258       data->vcolours = new TEL_COLOUR[data->num_vertices];
259       memcpy( data->vcolours, k[i]->data.pdata, data->num_vertices*sizeof(TEL_COLOUR) );
260       break;
261
262     case VNORMALS_ID:
263       data->vertex_flag = TEL_VT_NORMAL;
264       data->vnormals = new TEL_POINT[data->num_vertices];
265       memcpy( data->vnormals, k[i]->data.pdata, data->num_vertices*sizeof(TEL_POINT) );
266       for( j = 0; j < data->num_vertices; j++ )
267         vecnrm( data->vnormals[j].xyz );
268       break;
269
270     case SHAPE_FLAG_ID:
271       data->shape_flag = k[i]->data.ldata;
272       break;
273     }
274   }
275
276   if( data->facet_flag != TEL_FA_NORMAL )
277   {
278 #ifdef BUC60823
279     TelGetPolygonNormal( data->vertices, NULL, 
280       data->num_vertices, data->fnormal.xyz );
281 #else
282     TelGetNormal( data->vertices[0].xyz, data->vertices[1].xyz,
283       data->vertices[2].xyz, data->fnormal.xyz );
284     vecnrm( data->fnormal.xyz );
285 #endif
286   }
287   ((tsm_elem_data)(d.pdata))->pdata = data;
288
289   return TSuccess;
290 }
291
292
293
294 static  TStatus
295 PolygonHolesDisplay( TSM_ELEM_DATA data, Tint n, cmn_key *k )
296 {
297   Tint           front_face = 1;
298   Tmatrix3       mat;
299   CMN_KEY        k11, k12, k13, k14, k16, k17, k19, k111,
300                  k112, k113, k117;
301
302   Tint           fl=0;
303   Tint           front_lighting_model, back_lighting_model;
304   Tint           front_lighting_model_preserve, back_lighting_model_preserve;
305   Tint           front_shading_method;
306   Tint           interior_style;
307   Tint           interior_index;
308   TEL_COLOUR     interior_colour, back_interior_colour;
309   TEL_COLOUR     point_colour, edge_colour;
310   TelCullMode    face_culling_mode;
311   Tint           face_distinguishing_mode;
312
313   tel_polygon_holes_data d;
314
315   k11.id          = TelFaceDistinguishingMode;
316   k12.id          = TelInteriorReflectanceEquation;
317   k13.id          = TelInteriorShadingMethod;
318   k14.id          = TelBackInteriorReflectanceEquation;
319   k16.id          = TelFaceCullingMode;
320   k17.id          = TelInteriorStyle;
321   k19.id          = TelInteriorStyleIndex;
322   k111.id         = TelInteriorColour;
323   k111.data.pdata = &interior_colour;
324   k112.id         = TelBackInteriorColour;
325   k112.data.pdata = &back_interior_colour;
326   k113.id         = TelPolymarkerColour;
327   k113.data.pdata = &point_colour;
328   k117.id         = TelEdgeColour;
329   k117.data.pdata = &edge_colour;
330
331   TsmGetAttri( 11, &k11, &k12, &k13, &k14, &k16, &k17,
332     &k19, &k111, &k112, &k113, &k117 );
333
334   face_distinguishing_mode = k11.data.ldata;
335   front_lighting_model     = k12.data.ldata;
336   front_lighting_model_preserve = k12.data.ldata;
337   front_shading_method     = k13.data.ldata;
338   back_lighting_model      = k14.data.ldata;
339   back_lighting_model_preserve = k14.data.ldata;
340   face_culling_mode        = (TelCullMode)k16.data.ldata;
341   interior_style           = k17.data.ldata;
342   interior_index           = k19.data.ldata;
343
344   if( k[0]->id == TOn )
345   {                          /* Use highlight colours */
346     TEL_HIGHLIGHT  hrep;
347     CMN_KEY kkk, kkl;
348
349     k11.id = TelHighlightIndex;
350     TsmGetAttri( 1, &k11 );
351     if( TelGetHighlightRep( TglActiveWs, k11.data.ldata, &hrep )
352       == TSuccess )
353     {
354       if( hrep.type == TelHLForcedColour )
355       {
356         edge_colour = back_interior_colour = interior_colour = hrep.col;
357         front_lighting_model = back_lighting_model = CALL_PHIGS_REFL_NONE;
358         kkk.id = TelInteriorReflectanceEquation;
359         kkk.data.ldata = CALL_PHIGS_REFL_NONE;
360         kkl.id = TelBackInteriorReflectanceEquation;
361         kkl.data.ldata = CALL_PHIGS_REFL_NONE;
362         TsmSetAttri( 2, &kkk, &kkl );
363         fl = 0;
364       }
365       else
366       {
367         edge_colour = hrep.col;
368         k[0]->id = TOff;
369       }
370     }
371     else
372     {
373       TelGetHighlightRep( TglActiveWs, 0, &hrep );
374       if( hrep.type == TelHLForcedColour )
375       {
376         back_interior_colour = interior_colour = hrep.col;
377         front_lighting_model = back_lighting_model = CALL_PHIGS_REFL_NONE;
378         kkk.id = TelInteriorReflectanceEquation;
379         kkk.data.ldata = CALL_PHIGS_REFL_NONE;
380         kkl.id = TelBackInteriorReflectanceEquation;
381         kkl.data.ldata = CALL_PHIGS_REFL_NONE;
382         TsmSetAttri( 2, &kkk, &kkl );
383         fl = 0;
384       }
385       else
386         k[0]->id = TOff;
387     }
388   }
389
390   d = (tel_polygon_holes_data)data.pdata;
391
392   glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat *) mat);
393
394   if( face_distinguishing_mode == TOn )
395   {
396     if( ( face_culling_mode == TelCullBack && front_face ) ||
397       ( face_culling_mode == TelCullNone && front_face )   )
398     {
399       glColor3fv( interior_colour.rgb );
400
401       draw_polygon_holes(d, interior_style, front_lighting_model, k[0]->id);
402     }
403     else if( ( face_culling_mode == TelCullFront && !front_face ) ||
404       ( face_culling_mode == TelCullNone  && !front_face ) )
405     {
406       /* CMN_KEY k; */
407       glColor3fv( back_interior_colour.rgb );
408
409       draw_polygon_holes( d, interior_style,
410         back_lighting_model, k[0]->id);
411     }
412   }
413   else
414   {
415     if( ( face_culling_mode == TelCullBack  && front_face  ) ||
416       ( face_culling_mode == TelCullFront && !front_face ) ||
417       ( face_culling_mode == TelCullNone )                    )
418     {
419       glColor3fv( interior_colour.rgb );
420
421       draw_polygon_holes(d, interior_style, front_lighting_model, k[0]->id);
422     }
423   }
424
425
426   /*A  remplacer par le call-back GLU_EDGE_FLAG , A TESTER */
427   draw_edges( d, mat, &edge_colour, face_distinguishing_mode,
428     face_culling_mode, interior_style, interior_style );
429
430   if( fl )
431   {
432     CMN_KEY kkk, kkl;
433
434     kkk.id = TelInteriorReflectanceEquation;
435     kkk.data.ldata = front_lighting_model_preserve;
436     kkl.id = TelBackInteriorReflectanceEquation;
437     kkl.data.ldata = back_lighting_model_preserve;
438     TsmSetAttri( 2, &kkk, &kkl );
439   }
440
441   return TSuccess;
442
443 }
444
445 static GLUtesselator *tripak;
446
447 static void
448 draw_polygon_holes( tel_polygon_holes_data d,
449                    Tint style, Tint u, Tint hflag )
450 {
451   long      i, j, m;
452
453   GLdouble  xyz[3];
454
455   tel_point  pvn;
456   tel_colour pfc, pvc;
457
458   pfc = d->fcolour;
459   pvc = d->vcolours;
460   pvn = d->vnormals;
461
462   if( hflag )
463   {
464     pvc = pfc = 0;
465   }
466
467   if( pfc )
468     glColor3fv( pfc->rgb );
469   if( u != CALL_PHIGS_REFL_NONE )
470     glNormal3fv( d->fnormal.xyz );
471
472   if( d->display == 0 )
473   {
474
475     if( u == CALL_PHIGS_REFL_NONE )
476     {
477       if( pvc )
478       {
479         bgntriangulate( d, (void (APIENTRY*)())out_vertex2 );
480       }
481       else
482       {
483         bgntriangulate( d, (void (APIENTRY*)())out_vertex1 );
484       }
485     }
486     else
487     {
488       if( pvn )
489       {
490         bgntriangulate( d, (void (APIENTRY*)())out_vertex3 );
491       }
492       else
493       {
494         bgntriangulate( d, (void (APIENTRY*)())out_vertex1 );
495       }
496     }
497     gluTessBeginPolygon( tripak, NULL );
498     for( i = 0, m = 0; i < d->num_bounds; i++ )
499     {
500       gluTessBeginContour( tripak );
501       for( j = 0; j < d->bounds[i]; j++ )
502       {
503         xyz[0] = d->vertices[m].xyz[0];
504         xyz[1] = d->vertices[m].xyz[1];
505         xyz[2] = d->vertices[m].xyz[2];
506 #ifndef WNT
507         gluTessVertex( tripak, xyz, (void *)m );
508 #else
509         {
510           GLdouble v[ 3 ];
511           v[ 0 ] = d -> vertices[ m ].xyz[ 0 ];
512           v[ 1 ] = d -> vertices[ m ].xyz[ 1 ];
513           v[ 2 ] = d -> vertices[ m ].xyz[ 2 ];
514
515           gluTessVertex (  tripak,  v, ( void* )m  );
516         }
517 #endif  /* WNT */
518         m++;
519       }
520       gluTessEndContour( tripak );
521     }
522     gluTessEndPolygon( tripak );
523     endtriangulate();
524   }
525   else
526   {
527     if( u == CALL_PHIGS_REFL_NONE )
528     {
529       if( pvc )
530         draw_tmesh( d, 2 );
531       else
532         draw_tmesh( d, 1 );
533     }
534     else
535     {
536       if( pvn )
537         draw_tmesh( d, 3 );
538       else
539         draw_tmesh( d, 1 );
540     }
541   }
542
543
544 }
545
546 static void
547 draw_tmesh( tel_polygon_holes_data d, Tint v )
548 {
549   Tint     i, j, k;
550   DISPLAY_ *dis;
551   SEQ_     *s;
552
553   dis = d->display;
554   for( i = 0; i < dis->num_of_seq; i++ )
555   {
556     s = &(dis->seq[i]);
557
558     glBegin(s->triangle_type);
559     switch( v )
560     {
561     case 1:
562       {
563         for( j = 0, k = 0; j < s->ts_num; j++ )
564         {
565           if ( s->tmesh_sequence[j] < (void *)0xffff ) {
566             glVertex3fv( d->vertices[ (long)s->tmesh_sequence[ j ] ].xyz );
567           }
568           else {
569             extra_vertex b = (extra_vertex)s->tmesh_sequence[j];
570             glVertex3fv( b->vert );
571           }
572         }
573         break;
574       }
575     case 2:
576       {
577         for( j = 0, k = 0; j < s->ts_num; j++ )
578         {
579           if ( s->tmesh_sequence[j] < (void *)0xffff ) {
580             glColor3fv( d->vcolours[ (long) s->tmesh_sequence[ j ] ].rgb );
581             glVertex3fv( d->vertices[ (long) s->tmesh_sequence[ j ] ].xyz );
582           } else {
583             extra_vertex b = (extra_vertex)s->tmesh_sequence[j];
584             glColor3fv( d->vcolours[(b->ind)].rgb);
585             glVertex3fv( b->vert );
586           }
587         }
588         break;
589       }
590     case 3:
591       {
592         for( j = 0, k = 0; j < s->ts_num; j++ )
593         {
594           if ( s->tmesh_sequence[j] < (void *)0xffff) {
595             glNormal3fv( d->vnormals[ (long) s->tmesh_sequence[ j ] ].xyz );
596             glVertex3fv( d->vertices[ (long) s->tmesh_sequence[ j ] ].xyz );
597           } else {
598             extra_vertex b = (extra_vertex)s->tmesh_sequence[j];
599             glNormal3fv( d->vnormals[(b->ind)].xyz);
600             glVertex3fv( b->vert );
601           }
602         }
603         break;
604       }
605     }
606     glEnd();
607   }
608 }
609
610
611 static  TStatus
612 PolygonHolesDelete( TSM_ELEM_DATA data, Tint n, cmn_key *k )
613 {
614   tel_polygon_holes_data p = (tel_polygon_holes_data)data.pdata;
615   if( p->fcolour )
616     //cmn_freemem( p->fcolour );
617     delete p->fcolour;
618   if( p->vertices )
619     //cmn_freemem( p->vertices );
620     delete[] p->vertices;
621   if( p->vcolours )
622     //cmn_freemem( p->vcolours );
623     delete[] p->vcolours;
624   if( p->vnormals )
625     //cmn_freemem( p->vnormals );
626     delete[] p->vnormals;
627   if( p->bounds )
628     //cmn_freemem( p->bounds );
629     delete[] p->bounds;
630   if( p->edgevis )
631     //cmn_freemem( p->edgevis );
632     delete[] p->edgevis;
633   if( p->display )
634   {
635     Tint i, j;
636
637     for( i = 0; i <  p->display->num_of_seq; i++ )
638     {
639       if( p->display->seq[i].tmesh_sequence ) {
640         for ( j = 0; j < p->display->seq[i].ts_num ; j++ ) {
641           if ( p->display->seq[i].tmesh_sequence[j]  >= (void *)0xffff )
642             free(p->display->seq[i].tmesh_sequence[j]);
643         }
644       }
645       delete[] p->display->seq[i].tmesh_sequence;
646     }
647     delete[] p->display->seq;    
648     delete p->display;
649   }
650
651
652   if (data.pdata)
653     delete data.pdata;
654   return TSuccess;
655 }
656
657
658 static  TStatus
659 PolygonHolesPrint( TSM_ELEM_DATA data, Tint n, cmn_key *k )
660 {
661   Tint                   i;
662   tel_polygon_holes_data p = (tel_polygon_holes_data)data.pdata;
663
664   fprintf( stdout, "TelPolygonHoles. Number of bounds: %d\n", p->num_bounds );
665   switch( p->shape_flag )
666   {
667   case TEL_SHAPE_UNKNOWN:
668     fprintf( stdout, "\t\tShape Flag : UNKNOWN\n" );
669     break;
670
671   case TEL_SHAPE_COMPLEX:
672     fprintf( stdout, "\t\tShape Flag : COMPLEX\n" );
673     break;
674
675   case TEL_SHAPE_CONCAVE:
676     fprintf( stdout, "\t\tShape Flag : CONCAVE\n" );
677     break;
678
679   case TEL_SHAPE_CONVEX:
680     fprintf( stdout, "\t\tShape Flag : CONVEX\n" );
681     break;
682
683   }
684   switch( p->facet_flag )
685   {
686   case TEL_FA_NONE:
687     if( p->fcolour )
688       fprintf( stdout, "\t\tFacet Flag : COLOUR\n" );
689     else
690       fprintf( stdout, "\t\tFacet Flag : NONE\n" );
691     break;
692
693   case TEL_FA_NORMAL:
694     if( p->fcolour )
695       fprintf( stdout, "\t\tFacet Flag : COLOURNORMAL\n" );
696     else
697       fprintf( stdout, "\t\tFacet Flag : NORMAL\n" );
698     break;
699   }
700   switch( p->vertex_flag )
701   {
702   case TEL_VT_NONE:
703     if( p->vcolours )
704       fprintf( stdout, "\t\tVertex Flag : COLOUR\n" );
705     else
706       fprintf( stdout, "\t\tVertex Flag : NONE\n" );
707     break;
708
709   case TEL_VT_NORMAL:
710     if( p->vcolours )
711       fprintf( stdout, "\t\tVertex Flag : COLOURNORMAL\n" );
712     else
713       fprintf( stdout, "\t\tVertex Flag : NORMAL\n" );
714     break;
715   }
716   fprintf( stdout, "\t\tFacet Normal : %g %g %g\n", p->fnormal.xyz[0],
717     p->fnormal.xyz[1],
718     p->fnormal.xyz[2] );
719   if( p->fcolour )
720     fprintf( stdout, "\t\tFacet Colour : %g %g %g\n", p->fcolour->rgb[0],
721     p->fcolour->rgb[1],
722     p->fcolour->rgb[2] );
723   else
724     fprintf( stdout, "\n\t\tFacet Colour not specified\n" );
725
726   if( p->edgevis )
727   {
728     fprintf( stdout, "\t\tEdge Visibility Data :\n" );
729     for( i = 0; i < p->num_vertices; i++ )
730       fprintf( stdout, "\t\t%d ", p->edgevis[i] );
731     fprintf( stdout, "\n" );
732   }
733
734   if( p->bounds )
735   {
736     fprintf( stdout, "\t\tBounds array :\n" );
737     for( i = 0; i < p->num_bounds; i++ )
738       fprintf( stdout, "\t\tb[%d] %d \n", i, p->bounds[i] );
739   }
740
741   if( p->vertices )
742   {
743     fprintf( stdout, "\n\t\tVertices : " );
744     for( i = 0; i < p->num_vertices; i++ )
745       fprintf( stdout, "\n\t\t v[%d] = %g %g %g", i,
746       p->vertices[i].xyz[0],
747       p->vertices[i].xyz[1],
748       p->vertices[i].xyz[2] );
749   }
750
751   fprintf( stdout, "\n" );
752   if( p->vcolours )
753   {
754     fprintf( stdout, "\n\t\tVertex Colours : " );
755     for( i = 0; i < p->num_vertices; i++ )
756       fprintf( stdout, "\n\t\t v[%d] = %g %g %g", i,
757       p->vcolours[i].rgb[0],
758       p->vcolours[i].rgb[1],
759       p->vcolours[i].rgb[2] );
760   }
761   else
762     fprintf( stdout, "\n\t\tVertex Colours not specified\n" );
763
764   if( p->vnormals )
765   {
766     fprintf( stdout, "\n\t\tVertex Normals : " );
767     for( i = 0; i < p->num_vertices; i++ )
768       fprintf( stdout, "\n\t\t v[%d] = %g %g %g", i,
769       p->vnormals[i].xyz[0],
770       p->vnormals[i].xyz[1],
771       p->vnormals[i].xyz[2] );
772   }
773   else
774     fprintf( stdout, "\n\t\tVertex Normals not specified\n" );
775   fprintf( stdout, "\n" );
776   return TSuccess;
777 }
778
779
780 static TStatus
781 PolygonHolesInquire( TSM_ELEM_DATA data, Tint n, cmn_key *k )
782 {
783   Tint             i, j;
784   Tint             size_reqd=0;
785   TStatus          status = TSuccess;
786   Tchar            *cur_ptr = 0;
787   tel_polygon_holes_data d = (tel_polygon_holes_data)data.pdata;
788
789   if( d->fcolour )
790     size_reqd += sizeof( TEL_COLOUR );
791
792   if( d->facet_flag == TEL_FA_NORMAL )
793     size_reqd += sizeof( TEL_POINT );
794
795   if( d->edgevis )
796     size_reqd += ( d->num_vertices * sizeof( Tint ) );
797
798   size_reqd += ( d->num_bounds * sizeof( Tint ) );
799
800   size_reqd += ( d->num_vertices * sizeof( TEL_POINT ) );
801
802   if( d->vcolours )
803     size_reqd += ( d->num_vertices * sizeof( TEL_COLOUR ) );
804
805   if( d->vertex_flag == TEL_VT_NORMAL )
806     size_reqd += ( d->num_vertices * sizeof( TEL_POINT ) );
807
808   for( i = 0; i < n; i++ )
809   {
810     switch( k[i]->id )
811     {
812     case INQ_GET_SIZE_ID:
813       {
814         k[i]->data.ldata = size_reqd;
815         break;
816       }
817
818     case INQ_GET_CONTENT_ID:
819       {
820         TEL_INQ_CONTENT *c;
821         Teldata         *w;
822
823         c = (tel_inq_content)k[i]->data.pdata;
824         c->act_size = size_reqd;
825         w = c->data;
826
827         cur_ptr = c->buf;
828         w->fillareaset3data.num_bounds = d->num_bounds;
829         w->fillareaset3data.shpflag = d->shape_flag;
830
831         if( d->edgevis )
832           w->fillareaset3data.edgflag = TOn;
833         else
834           w->fillareaset3data.edgflag = TOff;
835
836         if( c->size >= size_reqd )
837         {
838           if( d->facet_flag == TEL_FA_NORMAL )
839           {
840             if( d->fcolour )
841             {
842               w->fillareaset3data.faflag = TEL_FAFLAG_COLOURNORMAL;
843               w->fillareaset3data.gnormal = (tel_point)(c->buf);
844               *(w->fillareaset3data.gnormal) = d->fnormal;
845               w->fillareaset3data.facet_colour_val =
846                 (tel_colour)(c->buf + sizeof( TEL_POINT ) );
847               *(w->fillareaset3data.facet_colour_val) = *(d->fcolour);
848               cur_ptr = c->buf + sizeof( TEL_POINT ) +
849                 sizeof( TEL_COLOUR );
850             }
851             else
852             {
853               w->fillareaset3data.faflag = TEL_FAFLAG_NORMAL;
854               w->fillareaset3data.facet_colour_val = 0;
855               w->fillareaset3data.gnormal = (tel_point)(c->buf);
856               *(w->fillareaset3data.gnormal) = d->fnormal;
857               cur_ptr = c->buf + sizeof( TEL_POINT );
858             }
859           }
860           else
861           {
862             w->fillareaset3data.gnormal = 0;
863             if( d->fcolour )
864             {
865               w->fillareaset3data.faflag = TEL_FAFLAG_COLOUR;
866               w->fillareaset3data.facet_colour_val = (tel_colour)(c->buf );
867               *(w->fillareaset3data.facet_colour_val) = *(d->fcolour);
868               cur_ptr = c->buf + sizeof( TEL_COLOUR );
869             }
870             else
871             {
872               w->fillareaset3data.faflag = TEL_FAFLAG_NONE;
873               w->fillareaset3data.facet_colour_val = 0;
874             }
875           }
876
877           w->fillareaset3data.points = (tel_point)cur_ptr;
878           for( j = 0; j < d->num_vertices; j++ )
879           {
880             w->fillareaset3data.points[j] = d->vertices[j];
881           }
882           cur_ptr += ( d->num_vertices * sizeof( TEL_POINT ) );
883
884           if( d->edgevis )
885           {
886             w->fillareaset3data.edgvis = (Tint *)(cur_ptr);
887             memcpy( w->fillareaset3data.edgvis, d->edgevis,
888               d->num_vertices*sizeof(Tint) );
889             cur_ptr += (d->num_vertices * sizeof( Tint ) );
890           }
891
892           w->fillareaset3data.bounds = (Tint *)cur_ptr;
893           memcpy( w->fillareaset3data.bounds, d->bounds,
894             d->num_bounds*sizeof(Tint) );
895           cur_ptr += ( d->num_bounds * sizeof( Tint ) );
896
897           if( d->vertex_flag == TEL_VT_NORMAL )
898           {
899             if( d->vcolours )
900             {
901               w->fillareaset3data.vrtflag = TEL_VTFLAG_COLOURNORMAL;
902               w->fillareaset3data.vnormals = (tel_point)(cur_ptr);
903               for( j = 0; j < d->num_vertices; j++ )
904               {
905                 w->fillareaset3data.vnormals[j] = d->vnormals[i];
906               }
907               cur_ptr += ( d->num_vertices * sizeof( TEL_POINT ) );
908
909               w->fillareaset3data.colours = (tel_colour)(cur_ptr);
910
911               for( j = 0; j < d->num_vertices; j++ )
912               {
913                 w->fillareaset3data.colours[j] = d->vcolours[i];
914               }
915             }
916             else
917             {
918               w->fillareaset3data.vrtflag = TEL_VTFLAG_NORMAL;
919               w->fillareaset3data.colours = 0;
920               w->fillareaset3data.vnormals = (tel_point)(cur_ptr);
921
922               for( j = 0; j < d->num_vertices; j++ )
923               {
924                 w->fillareaset3data.vnormals[j] = d->vnormals[i];
925               }
926             }
927           }
928           else
929           {
930             w->fillareaset3data.vnormals = 0;
931             if( d->vcolours )
932             {
933               w->fillareaset3data.vrtflag = TEL_VTFLAG_COLOUR;
934               w->fillareaset3data.colours = (tel_colour)(cur_ptr);
935               for( j = 0; j < d->num_vertices; j++ )
936               {
937                 w->fillareaset3data.colours[j] = d->vcolours[i];
938               }
939             }
940             else
941             {
942               w->fillareaset3data.vrtflag = TEL_VTFLAG_NONE;
943               w->fillareaset3data.colours = 0;
944             }
945           }
946
947           status = TSuccess;
948         }
949         else
950           status = TFailure;
951         break;
952       }
953     }
954   }
955   return status;
956 }
957
958
959
960 #define INCREMENT    64
961 static tel_polygon_holes_data DaTa;
962
963 STATIC void APIENTRY
964 out_bgntmesh_1 ( GLenum triangle_type )
965 {
966
967   DISPLAY_ *dis;
968   dis = DaTa->display;
969
970   dis->num_of_seq++;
971   if( dis->num_alloc < dis->num_of_seq )
972   {
973     dis->num_alloc += INCREMENT;
974
975     if( dis->seq == 0 )
976     {
977       dis->seq = new SEQ_[dis->num_alloc];
978     }
979     else
980     {
981 #if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x530)
982       dis->seq = (SEQ_*)realloc( dis->seq, dis->num_alloc*sizeof(SEQ_) );
983 #else
984       dis->seq = cmn_resizemem<SEQ_>( dis->seq, dis->num_alloc );
985 #endif
986     }
987   }
988   dis->seq[ dis->num_of_seq - 1 ].ts_num = 0;
989   dis->seq[ dis->num_of_seq - 1 ].ts_alloc = 0;
990   dis->seq[ dis->num_of_seq - 1 ].tmesh_sequence = 0;
991   dis->seq[ dis->num_of_seq - 1 ].triangle_type = triangle_type;
992   glBegin(triangle_type);
993 }
994
995
996 STATIC void APIENTRY
997 out_vertex1( void *data )
998 {
999   SEQ_ *s;
1000
1001   s = &( DaTa->display->seq[ DaTa->display->num_of_seq - 1 ] );
1002
1003   s->ts_num++;
1004   if( s->ts_alloc < s->ts_num )
1005   {
1006     s->ts_alloc += INCREMENT;
1007
1008     if( s->tmesh_sequence == 0 )
1009     {
1010       s->tmesh_sequence = new void*[s->ts_alloc];
1011     }
1012     else
1013     {
1014 #if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x530)
1015       s->tmesh_sequence = (void**)realloc( s->tmesh_sequence,
1016         s->ts_alloc*sizeof(void*));
1017 #else
1018       s->tmesh_sequence = cmn_resizemem<void*>( s->tmesh_sequence,
1019         s->ts_alloc);
1020 #endif          
1021     }
1022   }
1023   s->tmesh_sequence[ s->ts_num - 1 ] = data;
1024
1025   if ( data < (void *)0xffff ) {
1026     long int a = (long int)data;
1027
1028     glVertex3fv( DaTa->vertices[a].xyz );
1029   }
1030   else {
1031     extra_vertex b = (extra_vertex)data;
1032
1033     glVertex3fv(b->vert);
1034   }
1035 }
1036
1037 STATIC void APIENTRY
1038 out_vertex2( void *data )
1039 {
1040   SEQ_ *s;
1041
1042   s = &( DaTa->display->seq[ DaTa->display->num_of_seq - 1 ] );
1043
1044   s->ts_num++;
1045   if( s->ts_alloc < s->ts_num )
1046   {
1047     s->ts_alloc += INCREMENT;
1048
1049     if( s->tmesh_sequence == 0 )
1050     {
1051       s->tmesh_sequence = new void*[s->ts_alloc];
1052     }
1053     else
1054     {
1055 #if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x530)
1056       s->tmesh_sequence = (void**)realloc( s->tmesh_sequence,
1057         s->ts_alloc*sizeof(void*) );
1058 #else
1059       s->tmesh_sequence = cmn_resizemem<void*>( s->tmesh_sequence,
1060         s->ts_alloc );
1061 #endif
1062     }
1063   }
1064   s->tmesh_sequence[ s->ts_num - 1 ] = data;
1065
1066   if ( data < (void *)0xffff ){
1067     long int a = (long int)data;
1068
1069     glColor3fv( DaTa->vcolours[a].rgb );
1070     glVertex3fv( DaTa->vertices[a].xyz );
1071   }
1072   else {
1073     extra_vertex b = (extra_vertex)data;
1074
1075     glColor3fv(DaTa->vcolours[b->ind].rgb );
1076     glVertex3fv(b->vert);
1077   }
1078 }
1079
1080 STATIC void APIENTRY
1081 out_vertex3( void *data )
1082 {
1083   SEQ_ *s;
1084
1085   s = &( DaTa->display->seq[ DaTa->display->num_of_seq - 1 ] );
1086
1087   s->ts_num++;
1088   if( s->ts_alloc < s->ts_num )
1089   {
1090     s->ts_alloc += INCREMENT;
1091
1092     if( s->tmesh_sequence == 0 )
1093     {
1094       s->tmesh_sequence = new void*[s->ts_alloc];
1095     }
1096     else
1097     {
1098 #if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x530)
1099       s->tmesh_sequence = (void**)realloc( s->tmesh_sequence,
1100         s->ts_alloc*sizeof(void*) );
1101 #else
1102       s->tmesh_sequence = cmn_resizemem<void*>( s->tmesh_sequence,
1103         s->ts_alloc );
1104 #endif
1105     }
1106   }
1107   s->tmesh_sequence[ s->ts_num - 1 ] = data;
1108
1109   if ( data < (void *)0xffff ) {
1110     long int a = (long int)data;
1111
1112     glNormal3fv( DaTa->vnormals[a].xyz );
1113     glVertex3fv( DaTa->vertices[a].xyz );
1114   }
1115   else {
1116     extra_vertex b = (extra_vertex) data;
1117
1118     glNormal3fv( DaTa->vnormals[b->ind].xyz );
1119     glVertex3fv(b->vert);
1120   }
1121
1122 }
1123
1124 STATIC void APIENTRY
1125 out_combine( GLdouble coords[3], int *data,
1126             GLfloat w[4], void **dataout )
1127 {
1128   extra_vertex  new_vertex;
1129
1130   new_vertex =  (extra_vertex) malloc(sizeof(EXTRA_VERTEX));
1131
1132   new_vertex->vert[0] = ( float )coords[0];
1133   new_vertex->vert[1] = ( float )coords[1];
1134   new_vertex->vert[2] = ( float )coords[2];
1135   new_vertex->ind =   *data;
1136   *dataout = new_vertex;
1137
1138 #ifdef TRACE
1139   printf("mycombine3 %e   %e   %e\n",
1140     new_vertex->vert[0],
1141     new_vertex->vert[1],
1142     new_vertex->vert[2],
1143     new_vertex->ind);
1144 #endif
1145
1146
1147 }
1148
1149
1150
1151 STATIC void APIENTRY
1152 out_endtmesh_1( void )
1153 {
1154   glEnd();
1155 }
1156
1157 STATIC void APIENTRY
1158 out_error_1( GLenum error )
1159 {
1160   printf( "%s\n", (char *) gluErrorString(error) );
1161 }
1162
1163 static void
1164 bgntriangulate( tel_polygon_holes_data d, void (APIENTRY*out_ver)() )
1165 {
1166   DaTa = d;
1167   if( !DaTa->display )
1168     DaTa->display = new DISPLAY_();
1169
1170   tripak = gluNewTess();
1171 #if defined(linux) && !defined(NOGLUfuncptr)
1172   gluTessCallback(tripak, GLU_TESS_BEGIN, (_GLUfuncptr)(out_bgntmesh_1));
1173   gluTessCallback(tripak, GLU_TESS_VERTEX, out_ver);
1174   gluTessCallback(tripak, GLU_TESS_END, out_endtmesh_1);
1175   gluTessCallback(tripak, GLU_TESS_ERROR, (_GLUfuncptr)(out_error_1));
1176   gluTessCallback(tripak, GLU_TESS_COMBINE, (_GLUfuncptr)(out_combine));
1177 #else 
1178   gluTessCallback(tripak, GLU_TESS_BEGIN, (void (APIENTRY*)())out_bgntmesh_1);
1179   gluTessCallback(tripak, GLU_TESS_VERTEX, (void (APIENTRY*)())out_ver);
1180   gluTessCallback(tripak, GLU_TESS_END, (void (APIENTRY*)())out_endtmesh_1);
1181   gluTessCallback(tripak, GLU_TESS_ERROR, (void (APIENTRY*)())out_error_1);
1182   gluTessCallback(tripak, GLU_TESS_COMBINE, (void (APIENTRY*)())out_combine);
1183 #endif
1184
1185 }
1186
1187 static void
1188 endtriangulate(void)
1189 {
1190   DaTa = 0;
1191   gluDeleteTess(tripak);
1192 }
1193
1194 static void
1195 draw_edges( tel_polygon_holes_data p, Tmatrix3 mat, tel_colour edge_colour,
1196            Tint face_distinguishing_mode, TelCullMode face_culling_mode,
1197            Tint interior_style, Tint back_interior_style )
1198 {
1199   CMN_KEY k, k1, k2, k3, k4;
1200   Tint    i, j, a, clos;
1201   Tint    edge_type, line_type_preserve;
1202   Tfloat  edge_width, line_width_preserve;
1203   /* Following pointers have been provided for performance improvement */
1204   Tint       *bounds;
1205   tel_point  pv;
1206
1207   /* OCC11904 -- Temporarily disable environment mapping */
1208   glPushAttrib(GL_ENABLE_BIT);
1209   glDisable(GL_TEXTURE_1D);
1210   glDisable(GL_TEXTURE_2D);
1211
1212
1213   bounds = p->bounds;
1214   pv  = p->vertices;
1215
1216   k.id = TelEdgeFlag;
1217   TsmGetAttri( 1, &k );
1218
1219   if( !p->edgevis )
1220     if( k.data.ldata == TOff )
1221     {
1222       glPopAttrib();
1223       return;
1224     }
1225
1226     k1.id  = TelPolylineWidth;
1227     k2.id  = TelPolylineType;
1228     k3.id  = TelEdgeType;
1229     k4.id  = TelEdgeWidth;
1230
1231     TsmGetAttri( 4, &k1, &k2, &k3, &k4 );
1232
1233     line_width_preserve = k1.data.fdata;
1234     line_type_preserve  = k2.data.ldata;
1235     edge_type           = k3.data.ldata;
1236     edge_width          = k4.data.fdata;
1237
1238     if( p->edgevis == 0 )
1239     {
1240       if( face_distinguishing_mode == TOff )
1241       {
1242         if( interior_style == TSM_SOLID || interior_style == TSM_HATCH )
1243         {
1244           if( line_width_preserve != edge_width )
1245           {
1246             k.id = TelPolylineWidth;
1247             k.data.fdata = edge_width;
1248             TsmSetAttri( 1, &k );
1249           }
1250           if( line_type_preserve != edge_type )
1251           {
1252             k.id = TelPolylineType;
1253             k.data.ldata = edge_type;
1254             TsmSetAttri( 1, &k );
1255           }
1256
1257           glColor3fv( edge_colour->rgb );
1258           if( face_culling_mode == TelCullBack )
1259           {
1260             for( i = 0, a = 0; i < p->num_bounds; i++ )
1261             {
1262               glBegin(GL_LINE_STRIP);
1263               for( clos=a, j = 0; j < bounds[i]; j++ )
1264               {
1265                 glVertex3fv( pv[ a++ ].xyz );
1266               }
1267               glVertex3fv( pv[ clos ].xyz );
1268               glEnd();
1269             }
1270           }
1271           else if( face_culling_mode == TelCullFront )
1272           {
1273             for( i = 0, a = 0; i < p->num_bounds; i++ )
1274             {
1275               glBegin(GL_LINE_STRIP);
1276               for( clos=a, j = 0; j < bounds[i]; j++ )
1277               {
1278                 glVertex3fv( pv[ a++ ].xyz );
1279               }
1280               glVertex3fv( pv[ clos ].xyz );
1281               glEnd();
1282             }
1283           }
1284           else
1285           {
1286             for( i = 0, a = 0; i < p->num_bounds; i++ )
1287             {
1288               glBegin(GL_LINE_STRIP);
1289               for( clos=a, j = 0; j < bounds[i]; j++ )
1290               {
1291                 glVertex3fv( pv[ a++ ].xyz );
1292               }
1293               glVertex3fv( pv[ clos ].xyz );
1294               glEnd();
1295             }
1296           }
1297           if( line_width_preserve != edge_width )
1298           {
1299             k.id = TelPolylineWidth;
1300             k.data.fdata = line_width_preserve;
1301             TsmSetAttri( 1, &k );
1302           }
1303           if( line_type_preserve != edge_type )
1304           {
1305             k.id = TelPolylineType;
1306             k.data.ldata = line_type_preserve;
1307             TsmSetAttri( 1, &k );
1308           }
1309         }
1310       }
1311       else
1312       {
1313         if( ( interior_style == TSM_SOLID      ||
1314           interior_style == TSM_HATCH         ) ||
1315           ( back_interior_style == TSM_SOLID ||
1316           back_interior_style == TSM_HATCH    ) )
1317         {
1318           if( face_culling_mode == TelCullBack )
1319           {
1320             if( interior_style == TSM_SOLID || interior_style == TSM_HATCH )
1321             {
1322               if( line_width_preserve != edge_width )
1323               {
1324                 k.id = TelPolylineWidth;
1325                 k.data.fdata = edge_width;
1326                 TsmSetAttri( 1, &k );
1327               }
1328               if( line_type_preserve != edge_type )
1329               {
1330                 k.id = TelPolylineType;
1331                 k.data.ldata = edge_type;
1332                 TsmSetAttri( 1, &k );
1333               }
1334               glColor3fv( edge_colour->rgb );
1335               for( i = 0, a = 0; i < p->num_bounds; i++ )
1336               {
1337                 glBegin(GL_LINE_STRIP);
1338                 for( clos=a, j = 0; j < bounds[i]; j++ )
1339                 {
1340                   glVertex3fv( pv[ a++ ].xyz );
1341                 }
1342                 glVertex3fv( pv[ clos ].xyz );
1343                 glEnd();
1344               }
1345               if( line_width_preserve != edge_width )
1346               {
1347                 k.id = TelPolylineWidth;
1348                 k.data.fdata = line_width_preserve;
1349                 TsmSetAttri( 1, &k );
1350               }
1351               if( line_type_preserve != edge_type )
1352               {
1353                 k.id = TelPolylineType;
1354                 k.data.ldata = line_type_preserve;
1355                 TsmSetAttri( 1, &k );
1356               }
1357             }
1358           }
1359           else if( face_culling_mode == TelCullFront )
1360           {
1361             if( back_interior_style == TSM_SOLID ||
1362               back_interior_style == TSM_HATCH )
1363             {
1364               if( line_width_preserve != edge_width )
1365               {
1366                 k.id = TelPolylineWidth;
1367                 k.data.fdata = edge_width;
1368                 TsmSetAttri( 1, &k );
1369               }
1370               if( line_type_preserve != edge_type )
1371               {
1372                 k.id = TelPolylineType;
1373                 k.data.ldata = edge_type;
1374                 TsmSetAttri( 1, &k );
1375               }
1376               glColor3fv( edge_colour->rgb );
1377               for( i = 0, a = 0; i < p->num_bounds; i++ )
1378               {
1379                 glBegin(GL_LINE_STRIP);
1380                 for( clos=a, j = 0; j < bounds[i]; j++ )
1381                 {
1382                   glVertex3fv( pv[ a++ ].xyz );
1383                 }
1384                 glVertex3fv( pv[ clos ].xyz );
1385                 glEnd();
1386               }
1387               if( line_width_preserve != edge_width )
1388               {
1389                 k.id = TelPolylineWidth;
1390                 k.data.fdata = line_width_preserve;
1391                 TsmSetAttri( 1, &k );
1392               }
1393               if( line_type_preserve != edge_type )
1394               {
1395                 k.id = TelPolylineType;
1396                 k.data.ldata = line_type_preserve;
1397                 TsmSetAttri( 1, &k );
1398               }
1399             }
1400           }
1401           else
1402           {
1403             if( line_width_preserve != edge_width )
1404             {
1405               k.id = TelPolylineWidth;
1406               k.data.fdata = edge_width;
1407               TsmSetAttri( 1, &k );
1408             }
1409             if( line_type_preserve != edge_type )
1410             {
1411               k.id = TelPolylineType;
1412               k.data.ldata = edge_type;
1413               TsmSetAttri( 1, &k );
1414             }
1415             glColor3fv( edge_colour->rgb );
1416             for( i = 0, a = 0; i < p->num_bounds; i++ )
1417             {
1418               glBegin(GL_LINE_STRIP);
1419               for( clos=a, j = 0; j < bounds[i]; j++ )
1420               {
1421                 glVertex3fv( pv[ a++ ].xyz );
1422               }
1423               glVertex3fv( pv[ clos ].xyz );
1424               glEnd();
1425             }
1426             if( line_width_preserve != edge_width )
1427             {
1428               k.id = TelPolylineWidth;
1429               k.data.fdata = line_width_preserve;
1430               TsmSetAttri( 1, &k );
1431             }
1432             if( line_type_preserve != edge_type )
1433             {
1434               k.id = TelPolylineType;
1435               k.data.ldata = line_type_preserve;
1436               TsmSetAttri( 1, &k );
1437             }
1438           }
1439         }
1440       }
1441     }
1442     else
1443     {
1444       if( face_distinguishing_mode == TOff )
1445       {
1446         if( interior_style == TSM_SOLID || interior_style == TSM_HATCH )
1447         {
1448           if( line_width_preserve != edge_width )
1449           {
1450             k.id = TelPolylineWidth;
1451             k.data.fdata = edge_width;
1452             TsmSetAttri( 1, &k );
1453           }
1454           if( line_type_preserve != edge_type )
1455           {
1456             k.id = TelPolylineType;
1457             k.data.ldata = edge_type;
1458             TsmSetAttri( 1, &k );
1459           }
1460
1461           glColor3fv( edge_colour->rgb );
1462           if( face_culling_mode == TelCullBack )
1463           {
1464             glBegin(GL_LINES);
1465             for( i = 0, j = 0; i < p->num_bounds; i++ )
1466             {
1467               for( a = 0; a < bounds[i]-1; a++ )
1468               {
1469                 if( p->edgevis[j+a] )
1470                 {
1471                   glVertex3fv( pv[j+a].xyz );
1472                   glVertex3fv( pv[j+a+1].xyz );
1473                 }
1474               }
1475               if( p->edgevis[j+a] )
1476               {
1477                 glVertex3fv( pv[j+a].xyz );
1478                 glVertex3fv( pv[j].xyz );
1479               }
1480               j += p->bounds[i];
1481             }
1482             glEnd();
1483           }
1484           else if( face_culling_mode == TelCullFront )
1485           {
1486             glBegin(GL_LINES);
1487             for( i = 0, j = 0; i < p->num_bounds; i++ )
1488             {
1489               for( a = 0; a < bounds[i]-1; a++ )
1490               {
1491                 if( p->edgevis[j+a] )
1492                 {
1493                   glVertex3fv( pv[j+a].xyz );
1494                   glVertex3fv( pv[j+a+1].xyz );
1495                 }
1496               }
1497               if( p->edgevis[j+a] )
1498               {
1499                 glVertex3fv( pv[j+a].xyz );
1500                 glVertex3fv( pv[j].xyz );
1501               }
1502               j += p->bounds[i];
1503             }
1504             glEnd();
1505           }
1506           else
1507           {
1508             glBegin(GL_LINES);
1509             for( i = 0, j = 0; i < p->num_bounds; i++ )
1510             {
1511               for( a = 0; a < bounds[i]-1; a++ )
1512               {
1513                 if( p->edgevis[j+a] )
1514                 {
1515                   glVertex3fv( pv[j+a].xyz );
1516                   glVertex3fv( pv[j+a+1].xyz );
1517                 }
1518               }
1519               if( p->edgevis[j+a] )
1520               {
1521                 glVertex3fv( pv[j+a].xyz );
1522                 glVertex3fv( pv[j].xyz );
1523               }
1524               j += p->bounds[i];
1525             }
1526             glEnd();
1527           }
1528           if( line_width_preserve != edge_width )
1529           {
1530             k.id = TelPolylineWidth;
1531             k.data.fdata = line_width_preserve;
1532             TsmSetAttri( 1, &k );
1533           }
1534           if( line_type_preserve != edge_type )
1535           {
1536             k.id = TelPolylineType;
1537             k.data.ldata = line_type_preserve;
1538             TsmSetAttri( 1, &k );
1539           }
1540         }
1541       }
1542       else
1543       {
1544         if( ( interior_style == TSM_SOLID      ||
1545           interior_style == TSM_HATCH         ) ||
1546           ( back_interior_style == TSM_SOLID ||
1547           back_interior_style == TSM_HATCH    ) )
1548         {
1549           if( face_culling_mode == TelCullBack )
1550           {
1551             if( interior_style == TSM_SOLID || interior_style == TSM_HATCH )
1552             {
1553               if( line_width_preserve != edge_width )
1554               {
1555                 k.id = TelPolylineWidth;
1556                 k.data.fdata = edge_width;
1557                 TsmSetAttri( 1, &k );
1558               }
1559               if( line_type_preserve != edge_type )
1560               {
1561                 k.id = TelPolylineType;
1562                 k.data.ldata = edge_type;
1563                 TsmSetAttri( 1, &k );
1564               }
1565               glColor3fv( edge_colour->rgb );
1566               glBegin(GL_LINES);
1567               for( i = 0, j = 0; i < p->num_bounds; i++ )
1568               {
1569                 for( a = 0; a < bounds[i]-1; a++ )
1570                 {
1571                   if( p->edgevis[j+a] )
1572                   {
1573                     glVertex3fv( pv[j+a].xyz );
1574                     glVertex3fv( pv[j+a+1].xyz );
1575                   }
1576                 }
1577                 if( p->edgevis[j+a] )
1578                 {
1579                   glVertex3fv( pv[j+a].xyz );
1580                   glVertex3fv( pv[j].xyz );
1581                 }
1582                 j += p->bounds[i];
1583               }
1584               glEnd();
1585               if( line_width_preserve != edge_width )
1586               {
1587                 k.id = TelPolylineWidth;
1588                 k.data.fdata = line_width_preserve;
1589                 TsmSetAttri( 1, &k );
1590               }
1591               if( line_type_preserve != edge_type )
1592               {
1593                 k.id = TelPolylineType;
1594                 k.data.ldata = line_type_preserve;
1595                 TsmSetAttri( 1, &k );
1596               }
1597             }
1598           }
1599           else if( face_culling_mode == TelCullFront )
1600           {
1601             if( back_interior_style == TSM_SOLID ||
1602               back_interior_style == TSM_HATCH )
1603             {
1604               if( line_width_preserve != edge_width )
1605               {
1606                 k.id = TelPolylineWidth;
1607                 k.data.fdata = edge_width;
1608                 TsmSetAttri( 1, &k );
1609               }
1610               if( line_type_preserve != edge_type )
1611               {
1612                 k.id = TelPolylineType;
1613                 k.data.ldata = edge_type;
1614                 TsmSetAttri( 1, &k );
1615               }
1616               glColor3fv( edge_colour->rgb );
1617               glBegin(GL_LINES);
1618               for( i = 0, j = 0; i < p->num_bounds; i++ )
1619               {
1620                 for( a = 0; a < bounds[i]-1; a++ )
1621                 {
1622                   if( p->edgevis[j+a] )
1623                   {
1624                     glVertex3fv( pv[j+a].xyz );
1625                     glVertex3fv( pv[j+a+1].xyz );
1626                   }
1627                 }
1628                 if( p->edgevis[j+a] )
1629                 {
1630                   glVertex3fv( pv[j+a].xyz );
1631                   glVertex3fv( pv[j].xyz );
1632                 }
1633                 j += p->bounds[i];
1634               }
1635               glEnd();
1636               if( line_width_preserve != edge_width )
1637               {
1638                 k.id = TelPolylineWidth;
1639                 k.data.fdata = line_width_preserve;
1640                 TsmSetAttri( 1, &k );
1641               }
1642               if( line_type_preserve != edge_type )
1643               {
1644                 k.id = TelPolylineType;
1645                 k.data.ldata = line_type_preserve;
1646                 TsmSetAttri( 1, &k );
1647               }
1648             }
1649           }
1650           else
1651           {
1652             if( line_width_preserve != edge_width )
1653             {
1654               k.id = TelPolylineWidth;
1655               k.data.fdata = edge_width;
1656               TsmSetAttri( 1, &k );
1657             }
1658             if( line_type_preserve != edge_type )
1659             {
1660               k.id = TelPolylineType;
1661               k.data.ldata = edge_type;
1662               TsmSetAttri( 1, &k );
1663             }
1664             glColor3fv( edge_colour->rgb );
1665             for( i = 0, j = 0; i < p->num_bounds; i++ )
1666             {
1667               glBegin(GL_LINES);
1668               for( a = 0; a < bounds[i]-1; a++ )
1669               {
1670                 if( p->edgevis[j+a] )
1671                 {
1672                   glVertex3fv( pv[j+a].xyz );
1673                   glVertex3fv( pv[j+a+1].xyz );
1674                 }
1675               }
1676               if( p->edgevis[j+a] )
1677               {
1678                 glVertex3fv( pv[j+a].xyz );
1679                 glVertex3fv( pv[j].xyz );
1680               }
1681               glEnd();
1682               j += p->bounds[i];
1683             }
1684
1685             if( line_width_preserve != edge_width )
1686             {
1687               k.id = TelPolylineWidth;
1688               k.data.fdata = line_width_preserve;
1689               TsmSetAttri( 1, &k );
1690             }
1691             if( line_type_preserve != edge_type )
1692             {
1693               k.id = TelPolylineType;
1694               k.data.ldata = line_type_preserve;
1695               TsmSetAttri( 1, &k );
1696             }
1697           }
1698         }
1699       }
1700     }
1701     glPopAttrib();
1702 }