Merging OCC22105, OCC22354, OCC22150 , OCC22199 , OCC22391 and OCC22108
[occt.git] / src / OpenGl / OpenGl_PrimitiveArray.cxx
1 /*
2 File OpenGl_PrimitiveArray.c
3
4 Created 16/06/2000 :  ATS : G005 : Modified version of OpenGl_indexpolygons.c, which use glDrawArrays or glDrawElements for rendering of primitive
5 21.06.03 : SAN : suppress display at all in animation mode if degenartion ratio == 1 (FULL_DEGENER)
6 03.07.03 : SAN : draw_degenerates_as_lines() function - all client states disabled except GL_VERTEX_ARRAY
7 in order to avoid exceptions in animation mode (OCC3192)
8 */
9
10 #define xOGLBUG         /* UNFORTUNATLY the edge flags are attached to vertexes 
11 and not to the edges. So the edge visibillity flags array 
12 is not usable.
13 */
14
15 #define xPRINT
16
17 #define TEST
18
19 #define FULL_DEGENER
20 #define OCC3192
21
22
23 #ifndef OGL_Max
24 #define OGL_Max(a,b) ((a) > (b) ? (a) : (b))
25 #endif
26
27 #ifndef OGL_Rand
28 static unsigned long vRand = 1L;
29 #define OGL_Rand() (vRand = vRand * 214013L + 2531011L)
30 #endif
31
32
33 #define OCC7833         /* ASL 26/01/05 transparency of polygon with colors assigned to vertices */
34
35 /*----------------------------------------------------------------------*/
36 /*
37 * Includes
38 */ 
39
40 #include <OpenGl_tgl_all.hxx>
41
42 #include <stddef.h>
43 #include <stdio.h>
44 #include <string.h>
45 #include <iostream>
46
47 #include <OpenGl_cmn_varargs.hxx>
48 #include <OpenGl_telem_attri.hxx>
49 #include <OpenGl_tsm.hxx>
50 #include <OpenGl_telem.hxx>
51 #include <OpenGl_telem_util.hxx>
52 #include <OpenGl_telem_highlight.hxx>
53 #include <OpenGl_telem_inquire.hxx>
54 #include <OpenGl_telem_view.hxx>
55 #include <OpenGl_tgl_funcs.hxx>
56 #include <OpenGl_LightBox.hxx>
57 #include <OpenGl_TextureBox.hxx>
58 #include <OpenGl_ResourceCleaner.hxx>
59 #include <OpenGl_ResourceVBO.hxx>
60 #include <InterfaceGraphic_PrimitiveArray.hxx>
61 #include <OpenGl_Memory.hxx>
62 #include <Standard.hxx>
63
64 # include <float.h>
65 # define DEF_DS_INTERNAL
66 # include <OpenGl_degeneration.hxx>
67
68 #include <OpenGl_Extension.hxx>
69
70 extern GLboolean g_fBitmap;
71
72 typedef CALL_DEF_PARRAY *call_def_parray;
73
74 #define GL_ARRAY_BUFFER_ARB           0x8892
75 #define GL_STATIC_DRAW_ARB            0x88E4
76 #define GL_ELEMENTS_ARRAY_BUFFER_ARB  0x8893
77 #define GL_EDGE_FLAG_ARRAY_EXT        0x8079
78
79 #ifdef WNT
80 typedef void (APIENTRY* PFNGLBINDBUFFERARBPROC)    (GLenum target, GLuint buffer);
81 typedef void (APIENTRY* PFNGLDELETEBUFFERSARBPROC) (GLsizei n, const GLuint *buffers);
82 typedef void (APIENTRY* PFNGLGENBUFFERSARBPROC)    (GLsizei n, GLuint *buffers);
83 typedef void (APIENTRY* PFNGLBUFFERDATAARBPROC)    (GLenum target, int size, const GLvoid *data, GLenum usage);
84 #else//WNT
85 typedef void (*PFNGLBINDBUFFERARBPROC)    (GLenum target, GLuint buffer);
86 typedef void (*PFNGLDELETEBUFFERSARBPROC) (GLsizei n, const GLuint *buffers);
87 typedef void (*PFNGLGENBUFFERSARBPROC)    (GLsizei n, GLuint *buffers);
88 #if defined ( __sgi ) 
89 typedef void (*PFNGLBUFFERDATAARBPROC)    (GLenum target, int size, const GLvoid *data, GLenum usage);
90 #else                                                              
91 typedef void (*PFNGLBUFFERDATAARBPROC)    (GLenum target, GLsizeiptrARB size, const GLvoid *data, GLenum usage);
92 #endif
93
94 #endif//WNT
95
96 PFNGLGENBUFFERSARBPROC    glVBOGenBuffersARB    = NULL; // VBO Name Generation Procedure
97 PFNGLBINDBUFFERARBPROC    glVBOBindBufferARB    = NULL; // VBO Bind Procedure
98 PFNGLBUFFERDATAARBPROC    glVBOBufferDataARB    = NULL; // VBO Data Loading Procedure
99 PFNGLDELETEBUFFERSARBPROC glVBODeleteBuffersARB = NULL; // VBO Data Deleting Procedure
100
101 int VBOExtension = 0;
102 int VBOenabled = 1;
103
104 #define VBO_NOT_INITIALIZED  -1
105 #define VBO_ERROR             0
106 #define VBO_OK                1
107
108 #ifndef WNT
109 #define glGetProcAddress( x )  glXGetProcAddress( (const GLubyte*) x )
110 #else
111 #define glGetProcAddress( x )  wglGetProcAddress( x )
112 #endif
113
114 void clearRAMMemory( CALL_DEF_PARRAY* p )
115 {
116     if( p->bufferVBO[VBOEdges] ){
117       Standard::Free((Standard_Address&)p->edges);
118       p->edges = NULL;
119     }
120     if( p->bufferVBO[VBOVertices] ){
121       Standard::Free((Standard_Address&)p->vertices);
122       p->vertices = NULL;
123     }
124     if( p->bufferVBO[VBOVcolours] ){
125       Standard::Free((Standard_Address&)p->vcolours);
126       p->vcolours = NULL;
127     }
128     if( p->bufferVBO[VBOVnormals] ){
129       Standard::Free((Standard_Address&)p->vnormals);
130       p->vnormals = NULL;
131     }
132     if( p->bufferVBO[VBOVtexels] ){
133       Standard::Free((Standard_Address&)p->vtexels);
134       p->vtexels = NULL;
135     }
136     if( p->edge_vis ){
137       Standard::Free((Standard_Address&)p->edge_vis);
138       p->edge_vis = NULL;
139     }
140 }
141
142 void clearGraphicRAMMemory( CALL_DEF_PARRAY* p )
143 {
144   if( p->bufferVBO[VBOEdges] ){
145     glVBODeleteBuffersARB( 1 , &p->bufferVBO[VBOEdges]);
146   }
147   if( p->bufferVBO[VBOVertices] ){
148     glVBODeleteBuffersARB( 1 , &p->bufferVBO[VBOVertices]);
149   }
150   if( p->bufferVBO[VBOVcolours] ){
151     glVBODeleteBuffersARB( 1 , &p->bufferVBO[VBOVcolours]);
152   }
153   if( p->bufferVBO[VBOVnormals] ){
154     glVBODeleteBuffersARB( 1 , &p->bufferVBO[VBOVnormals]);
155   } 
156   if( p->bufferVBO[VBOVtexels] ){
157     glVBODeleteBuffersARB( 1 , &p->bufferVBO[VBOVtexels]);
158   }
159   glVBOBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); 
160   glVBOBindBufferARB(GL_ELEMENTS_ARRAY_BUFFER_ARB, 0); 
161 }
162
163 int checkSizeForGraphicMemory( CALL_DEF_PARRAY* p )
164 {
165   if( GL_OUT_OF_MEMORY == glGetError() ){
166     p->flagBufferVBO = VBO_ERROR;
167     clearGraphicRAMMemory(p);
168   }
169   else 
170     p->flagBufferVBO = VBO_OK;
171   return p->flagBufferVBO ;
172 }
173
174 int initVBO()
175 {
176   if(CheckExtension((char *)"GL_ARB_vertex_buffer_object",(const char *)glGetString( GL_EXTENSIONS ))){
177     glVBOGenBuffersARB = (PFNGLGENBUFFERSARBPROC) glGetProcAddress("glGenBuffersARB");
178     glVBOBindBufferARB = (PFNGLBINDBUFFERARBPROC) glGetProcAddress("glBindBufferARB");
179     glVBOBufferDataARB = (PFNGLBUFFERDATAARBPROC) glGetProcAddress("glBufferDataARB");
180     glVBODeleteBuffersARB = (PFNGLDELETEBUFFERSARBPROC) glGetProcAddress("glDeleteBuffersARB");
181     VBOExtension = 1;
182     return 1;
183   }
184   return 0;
185 }
186
187 static void  BuildVBO( CALL_DEF_PARRAY* p )
188 {
189   int size_reqd = 0;
190   if( p->edges ){
191     size_reqd = ( p->num_edges * sizeof( Tint ) );
192     glVBOGenBuffersARB( 1, &p->bufferVBO[VBOEdges] );   
193     glVBOBindBufferARB( GL_ELEMENTS_ARRAY_BUFFER_ARB, p->bufferVBO[VBOEdges] );
194     glVBOBufferDataARB( GL_ELEMENTS_ARRAY_BUFFER_ARB, size_reqd , p->edges, GL_STATIC_DRAW_ARB );
195     if( checkSizeForGraphicMemory( p ) == VBO_ERROR ) 
196       return;
197   }
198
199   if( p->vertices ){
200     size_reqd = ( p->num_vertexs * sizeof( TEL_POINT ) );
201     glVBOGenBuffersARB( 1, &p->bufferVBO[VBOVertices]); 
202     glVBOBindBufferARB( GL_ARRAY_BUFFER_ARB, p->bufferVBO[VBOVertices] );
203     glVBOBufferDataARB( GL_ARRAY_BUFFER_ARB, size_reqd , p->vertices, GL_STATIC_DRAW_ARB );
204     if( checkSizeForGraphicMemory( p ) == VBO_ERROR ) 
205       return;
206   }
207
208   if( p->vcolours ){
209     size_reqd = ( p->num_vertexs * sizeof( Tint ) );
210     glVBOGenBuffersARB( 1, &p->bufferVBO[VBOVcolours] );
211     glVBOBindBufferARB( GL_ARRAY_BUFFER_ARB, p->bufferVBO[VBOVcolours]); 
212     glVBOBufferDataARB( GL_ARRAY_BUFFER_ARB, size_reqd , p->vcolours, GL_STATIC_DRAW_ARB );
213     if( checkSizeForGraphicMemory( p ) == VBO_ERROR ) 
214       return;
215   }
216
217   if( p->vnormals ){
218     size_reqd = ( p->num_vertexs * sizeof( TEL_POINT ) );
219     glVBOGenBuffersARB( 1, &p->bufferVBO[VBOVnormals] ); 
220     glVBOBindBufferARB( GL_ARRAY_BUFFER_ARB, p->bufferVBO[VBOVnormals] );
221     glVBOBufferDataARB( GL_ARRAY_BUFFER_ARB, size_reqd , p->vnormals, GL_STATIC_DRAW_ARB );
222     if( checkSizeForGraphicMemory( p ) == VBO_ERROR) 
223       return;
224   }
225
226   if( p->vtexels ){
227     size_reqd = ( p->num_vertexs * sizeof( TEL_TEXTURE_COORD ) );
228     glVBOGenBuffersARB( 1, &p->bufferVBO[VBOVtexels] ); 
229     glVBOBindBufferARB( GL_ARRAY_BUFFER_ARB, p->bufferVBO[VBOVtexels] ); 
230     glVBOBufferDataARB( GL_ARRAY_BUFFER_ARB, size_reqd , p->vtexels , GL_STATIC_DRAW_ARB );
231     if( checkSizeForGraphicMemory( p ) == VBO_ERROR ) 
232       return;
233   } 
234
235   if( p->flagBufferVBO == VBO_OK )
236     clearRAMMemory(p);
237
238   //specify context for VBO resource
239   p->contextId = (Standard_Address)GET_GL_CONTEXT();
240
241 }
242
243 /*----------------------------------------------------------------------*/
244 /*
245 * Constantes
246 */ 
247
248 /*----------------------------------------------------------------------*/
249 /*
250 * Prototypes
251 */ 
252
253 static  TStatus  ParrayDisplay( TSM_ELEM_DATA, Tint, cmn_key* );
254 static  TStatus  ParrayAdd( TSM_ELEM_DATA, Tint, cmn_key* );
255 static  TStatus  ParrayDelete( TSM_ELEM_DATA, Tint, cmn_key* );
256 static  TStatus  ParrayPrint( TSM_ELEM_DATA, Tint, cmn_key* );
257 static  TStatus  ParrayInquire( TSM_ELEM_DATA, Tint, cmn_key* );
258
259 /*static  GLboolean       lighting_mode;*/
260
261 static void draw_array(
262                        call_def_parray,
263                        Tint,          /* highlight_flag */
264                        Tint,          /* front_lighting_model,  */
265                        Tint,          /* interior_style,  */
266                        Tint,          /* edge_flag,  */
267                        tel_colour,    /* interior_colour, */
268                        tel_colour,    /* line_colour, */
269                        tel_colour     /* edge_colour, */
270 #ifdef OCC7833
271                        ,tel_surf_prop
272 #endif
273                        );
274
275 static void draw_edges                 ( call_def_parray, tel_colour );
276 static void draw_degenerates_as_points ( call_def_parray, tel_colour );
277 static void draw_degenerates_as_lines  ( call_def_parray, tel_colour );
278 static void draw_degenerates_as_bboxs  ( call_def_parray, tel_colour );
279
280 static  TStatus  (*MtdTbl[])( TSM_ELEM_DATA, Tint, cmn_key* ) =
281 {
282   NULL,             /* PickTraverse */
283   ParrayDisplay,
284   ParrayAdd,
285   ParrayDelete,
286   0,
287   0
288 };
289 static GLenum draw_mode;
290
291 /*----------------------------------------------------------------------*/
292 /*
293 * Variables externes
294 */
295
296 extern  Tint  ForbidSetTextureMapping; /* currently defined in tsm/tsm.c */
297
298 extern int   g_nDegenerateModel;
299 extern float g_fSkipRatio;
300
301 /*----------------------------------------------------------------------*/
302
303 MtblPtr
304 TelParrayInitClass( TelType* el )
305 {
306   *el = TelParray;
307   return MtdTbl;
308 }
309
310 /*----------------------------------------------------------------------*/
311
312 static  TStatus
313 ParrayAdd( TSM_ELEM_DATA d, Tint n, cmn_key *k )
314 {
315
316   if( k[0]->id != PARRAY_ID ) return TFailure;
317
318   ((tsm_elem_data)(d.pdata))->pdata = k[0]->data.pdata;
319
320   return TSuccess;
321 }
322
323 /*----------------------------------------------------------------------*/
324
325 static  TStatus
326 ParrayDisplay( TSM_ELEM_DATA data, Tint n, cmn_key *k )
327 {
328   CMN_KEY       k11, k12, k17, k18, k111, k114, k115;
329
330   Tint           front_lighting_model;
331   Tint           interior_style;
332   TEL_COLOUR     interior_colour;
333   TEL_COLOUR     edge_colour;
334   TEL_COLOUR     line_colour;
335   Tint           edge_flag;
336
337 #ifdef OCC7833
338   CMN_KEY        k117;
339   TEL_SURF_PROP  prop;
340 #endif
341
342   call_def_parray d = (call_def_parray)data.pdata;
343
344   k12.id          = TelInteriorReflectanceEquation;
345   k17.id          = TelInteriorStyle;
346   k18.id          = TelEdgeFlag;
347   k111.id         = TelInteriorColour;
348   k111.data.pdata = &interior_colour;
349   k114.id         = TelEdgeColour;
350   k114.data.pdata = &edge_colour;
351   k115.id         = TelPolylineColour;
352   k115.data.pdata = &line_colour;
353
354 #ifdef OCC7833
355   k117.id         = TelSurfaceAreaProperties;
356   k117.data.pdata = &prop;
357 #endif
358
359 #ifdef OCC7833
360   TsmGetAttri( 7, &k12, &k17, &k18, &k111, &k114, &k115, &k117 );
361 #else
362   TsmGetAttri( 6, &k12, &k17, &k18, &k111, &k114, &k115 );
363 #endif
364
365   front_lighting_model     = k12.data.ldata;
366   interior_style           = k17.data.ldata;
367   edge_flag                = k18.data.ldata;
368
369 #ifdef PRINT
370   printf("ParrayDisplay type %d\n",d->type); 
371 #endif
372
373   /* 
374   * Use highlight colours 
375   */
376
377   if( k[0]->id == TOn ) {
378     TEL_HIGHLIGHT  hrep;
379
380     k11.id = TelHighlightIndex;
381     TsmGetAttri( 1, &k11 );
382     if( TelGetHighlightRep( TglActiveWs, k11.data.ldata, &hrep ) == TSuccess ) {
383       if( hrep.type == TelHLForcedColour ) {
384         edge_colour = interior_colour = line_colour = hrep.col;
385         front_lighting_model = CALL_PHIGS_REFL_NONE;
386       } else if( hrep.type == TelHLColour ) {
387         edge_colour = hrep.col;
388         k[0]->id = TOff;
389       }
390     } else {
391       TelGetHighlightRep( TglActiveWs, 0, &hrep );
392       if( hrep.type == TelHLForcedColour ) {
393         edge_colour = interior_colour = line_colour = hrep.col;
394         front_lighting_model = CALL_PHIGS_REFL_NONE;
395       } else if( hrep.type == TelHLColour ) {
396         edge_colour = hrep.col;
397         k[0]->id = TOff;
398       }
399     }
400   }
401
402   draw_array( d, k[0]->id,
403     front_lighting_model,
404     interior_style,
405     edge_flag,     
406     &interior_colour,
407     &line_colour,
408     &edge_colour
409 #ifdef OCC7833
410     ,&prop
411 #endif
412     );
413
414   return TSuccess;
415
416 }
417
418 /*----------------------------------------------------------------------*/
419
420 static void 
421 draw_primitive_array( call_def_parray p, GLenum mode, GLint first, GLsizei count )
422 {
423   int i;
424   glBegin( mode );
425   for( i=first; i<(first + count); i++ ){
426     if( p->vnormals )
427       glNormal3fv( p->vnormals[i].xyz );
428     if( p->vtexels && !ForbidSetTextureMapping )
429       glTexCoord3fv( p->vtexels[i].xy );
430     if( p->vertices )
431       glVertex3fv( p->vertices[i].xyz );
432     if ( p->vcolours )
433       glColor4ubv( (GLubyte*) p->vcolours[i] );
434   }
435   glEnd();
436 }
437
438 /*----------------------------------------------------------------------*/
439 static void 
440 draw_primitive_elements( call_def_parray p, GLenum mode, GLsizei count, GLenum type, GLenum *indices )
441 {
442   int i;
443   GLenum index;
444   glBegin( mode );
445   for( i=0; i<count; i++ ){
446     index = indices[i];
447     if( p->vnormals )
448       glNormal3fv( p->vnormals[index].xyz );
449     if( p->vtexels && !ForbidSetTextureMapping )
450       glTexCoord3fv( p->vtexels[index].xy );
451     if( p->vertices ) 
452       glVertex3fv( p->vertices[index].xyz );
453      if ( p->vcolours ) 
454       glColor4ubv( (GLubyte*) p->vcolours[index] );
455   }
456   glEnd();
457 }
458 /*----------------------------------------------------------------------*/
459 static void
460 draw_array( call_def_parray p, Tint hflag,
461              Tint lighting_model,
462              Tint interior_style,
463              Tint edge_flag,
464              tel_colour interior_colour,
465              tel_colour line_colour,
466              tel_colour edge_colour
467 #ifdef OCC7833
468              ,tel_surf_prop prop
469 #endif
470              ){
471   Tint i,n;
472   Tint transp = 0;
473   GLint renderMode;
474   /* Following pointers have been provided for performance improvement */
475   tel_colour pfc;
476   Tint * pvc;
477
478   pvc = p->vcolours;
479   pfc = p->fcolours;
480
481 #ifdef OCC7833
482   if( pvc ){
483     for( i=0; i<p->num_vertexs; i++ ){
484       transp = (int)(prop->trans * 255.);
485 #if defined (sparc) || defined (__sparc__) || defined (__sparc) 
486       pvc[i] = ( pvc[i] & 0xffffff00 );
487       pvc[i] += transp ;
488                         
489 #else     
490       pvc[i] = ( pvc[i] & 0x00ffffff );
491       pvc[i] += transp << 24;
492 #endif
493     }
494   }
495 #endif
496
497   switch( p->type ) {
498     case TelPointsArrayType:
499       draw_mode = GL_POINTS; 
500       glColor3fv( line_colour->rgb );
501       break;
502     case TelPolylinesArrayType:
503       draw_mode = GL_LINE_STRIP; 
504       glColor3fv( line_colour->rgb );
505       break;
506     case TelSegmentsArrayType:
507       draw_mode = GL_LINES;
508       glColor3fv( line_colour->rgb );
509       break;
510     case TelPolygonsArrayType:
511       draw_mode = GL_POLYGON;
512       glColor3fv( interior_colour->rgb );
513       break;
514     case TelTrianglesArrayType:
515       draw_mode = GL_TRIANGLES;
516       glColor3fv( interior_colour->rgb );
517       break;
518     case TelQuadranglesArrayType:
519       draw_mode = GL_QUADS;
520       glColor3fv( interior_colour->rgb );
521       break;
522     case TelTriangleStripsArrayType:
523       draw_mode = GL_TRIANGLE_STRIP;
524       glColor3fv( interior_colour->rgb );
525       break;
526     case TelQuadrangleStripsArrayType:
527       draw_mode = GL_QUAD_STRIP;
528       glColor3fv( interior_colour->rgb );
529       break;
530     case TelTriangleFansArrayType:
531       draw_mode = GL_TRIANGLE_FAN;
532       glColor3fv( interior_colour->rgb );
533       break;
534     default:
535       return;
536   }
537
538    /* OCC11904 -- Temporarily disable environment mapping */
539   if( draw_mode <= GL_LINE_STRIP ){
540     glPushAttrib(GL_ENABLE_BIT);
541     glDisable(GL_TEXTURE_1D);
542     glDisable(GL_TEXTURE_2D);
543   }
544
545   if( p->VBOEnabled == -1 ){
546       p->VBOEnabled = VBOenabled;
547       if( VBOExtension == 0)
548         initVBO();
549       if( (VBOExtension == 1) && (p->VBOEnabled != 0))
550         BuildVBO( p );
551   }
552
553
554   #ifdef PRINT
555   printf(" $$$ g_nDegenerateModel %d\n",g_nDegenerateModel);
556   #endif
557   if ( g_nDegenerateModel < 2 && 
558      ( (draw_mode > GL_LINE_STRIP && interior_style != TSM_EMPTY) ||
559        (draw_mode <= GL_LINE_STRIP /*&& !hflag*/)) ) {
560
561     if( hflag == TOn ) {
562       pfc = NULL;
563       pvc = NULL;
564     }
565
566     if ( interior_style == TSM_HIDDENLINE) {
567       edge_flag = 1;
568       pfc = NULL;
569       pvc = NULL;
570     }
571
572     /*OCC12297 - Sometimes the GL_LIGHTING mode is activated here
573     without LightOn() call for an unknown reason, so it is necessary 
574     to call LightOn() to synchronize LightOn/Off mechanism*/
575     LightOn();
576
577     if( lighting_model == CALL_PHIGS_REFL_NONE || draw_mode <= GL_LINE_STRIP )
578         LightOff();
579
580     glGetIntegerv( GL_RENDER_MODE, &renderMode );
581
582     if ( p->num_vertexs > 0 && p->flagBufferVBO != VBO_OK) {
583       if( renderMode != GL_FEEDBACK ){
584           if( p->vertices ) {
585             glVertexPointer(3, GL_FLOAT, 0, p->vertices);/* array of vertices  */
586             glEnableClientState(GL_VERTEX_ARRAY);
587           }
588
589           if( p->vnormals ) {
590             glNormalPointer(GL_FLOAT, 0, p->vnormals);/* array of normals  */
591             glEnableClientState(GL_NORMAL_ARRAY);
592           }
593
594           if ( p->vtexels) {
595             glTexCoordPointer(2, GL_FLOAT, 0, p->vtexels);/* array of texture coordinates  */
596             glEnableClientState(GL_TEXTURE_COORD_ARRAY);
597           }
598
599           if ( pvc ) {
600 #ifdef OCC7833
601             glColorPointer(4, GL_UNSIGNED_BYTE, 0, pvc);  /* array of colors */
602 #else
603             glColorPointer(3, GL_UNSIGNED_BYTE, 0, pvc);  /* array of colors */
604 #endif
605             glEnableClientState(GL_COLOR_ARRAY);
606             glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE);
607             glEnable(GL_COLOR_MATERIAL);
608           }
609       }
610     }
611
612     //Bindings concrete pointer in accordance with VBO buffer
613     //Using VBO
614     if ( p->num_vertexs > 0 && p->flagBufferVBO == VBO_OK ) {
615       if( p->bufferVBO[VBOVertices] ){
616         glVBOBindBufferARB( GL_ARRAY_BUFFER_ARB, p->bufferVBO[VBOVertices]);
617         glVertexPointer(3, GL_FLOAT, 0, (char *) NULL);// array of vertices 
618         glEnableClientState(GL_VERTEX_ARRAY);
619       }
620
621       if( p->bufferVBO[VBOVnormals] ){
622         glVBOBindBufferARB( GL_ARRAY_BUFFER_ARB,  p->bufferVBO[VBOVnormals]);
623         glNormalPointer(GL_FLOAT, 0, (char *) NULL);// array of normals  
624         glEnableClientState(GL_NORMAL_ARRAY);
625       }
626
627       if ( p->bufferVBO[VBOVtexels] && !ForbidSetTextureMapping ) {
628         glVBOBindBufferARB( GL_ARRAY_BUFFER_ARB,  p->bufferVBO[VBOVtexels]);
629         glTexCoordPointer(2, GL_FLOAT, 0, (char *) NULL);/* array of texture coordinates */
630         glEnableClientState(GL_TEXTURE_COORD_ARRAY);
631       }
632
633       if ( p->bufferVBO[VBOVcolours] ) {
634         glVBOBindBufferARB( GL_ARRAY_BUFFER_ARB,  p->bufferVBO[VBOVcolours]);
635         glColorPointer( 4, GL_UNSIGNED_BYTE, 0, (char *) NULL);// array of colors 
636         glEnableClientState(GL_COLOR_ARRAY);
637         glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE);
638         glEnable(GL_COLOR_MATERIAL);
639       }
640     }
641     // OCC22236 NOTE: draw for all situations:
642     // 1) draw elements from p->bufferVBO[VBOEdges] indicies array
643     // 2) draw elements from vertice array, when bounds defines count of primitive's verts.
644     // 3) draw primitive by vertexes if no edges and bounds array is specified
645     if(  p->flagBufferVBO == VBO_OK ){
646       if ( p->num_edges > 0 && p->bufferVBO[VBOEdges] ) {
647         glVBOBindBufferARB(GL_ELEMENTS_ARRAY_BUFFER_ARB, p->bufferVBO[VBOEdges]); // for edge indices
648         
649         // draw primitives by vertex count with the indicies
650         if( p->num_bounds > 0 ) {
651           Tint* offset = 0;
652           for( i = 0, offset = 0 ; i < p->num_bounds ; i++ ) {
653             glDrawElements(draw_mode, p->bounds[i], GL_UNSIGNED_INT, offset);
654             offset += p->bounds[i]; 
655           }
656         }
657         // draw one (or sequential) primitive by the indicies
658         else {
659           glDrawElements(draw_mode, p->num_edges , GL_UNSIGNED_INT, 0);
660         }
661       }
662       else if( p->num_bounds > 0 ) {
663         for( i = n = 0 ; i < p->num_bounds ; i ++ ){
664           glDrawArrays(draw_mode, n, p->bounds[i]);
665           n += p->bounds[i];
666         }
667       }
668       else {
669         glDrawArrays(draw_mode, 0, p->num_vertexs);
670       }
671
672       //bind with 0
673       glVBOBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); 
674       glVBOBindBufferARB(GL_ELEMENTS_ARRAY_BUFFER_ARB, 0); 
675     } 
676     else {
677       if( p->num_bounds > 0 ) {
678         if( p->num_edges > 0 ) {
679             for( i=n=0 ; i<p->num_bounds ; i++ ) {
680               if( pfc ) glColor3fv  ( pfc[i].rgb  );
681               if( renderMode == GL_FEEDBACK )
682                 draw_primitive_elements( p, draw_mode, p->bounds[i], 
683                                         GL_UNSIGNED_INT,(GLenum*) &p->edges[n]);
684               else
685                 glDrawElements( draw_mode, p->bounds[i], 
686                                 GL_UNSIGNED_INT, &p->edges[n]);
687               n += p->bounds[i];
688             }
689         } else {
690           for( i=n=0 ; i<p->num_bounds ; i++ ) {
691                 if( pfc ) 
692                   glColor3fv  ( pfc[i].rgb  );
693                 if( renderMode == GL_FEEDBACK )
694                   draw_primitive_array( p, draw_mode, n, p->bounds[i]);
695                 else
696                 {
697                   glDrawArrays( draw_mode, n, p->bounds[i]);
698                 }
699                 n += p->bounds[i];
700               }
701             }
702       } else if( p->num_edges > 0 ) {
703           if( renderMode == GL_FEEDBACK )
704             draw_primitive_elements( p, draw_mode, p->num_edges, 
705                                     GL_UNSIGNED_INT,(GLenum*) &p->edges[0]);
706           else
707          glDrawElements( draw_mode, p->num_edges, GL_UNSIGNED_INT, p->edges);
708       } else {
709             if( renderMode == GL_FEEDBACK )
710             draw_primitive_array( p, draw_mode, 0, p->num_vertexs);
711           else
712             glDrawArrays( draw_mode, 0, p->num_vertexs);
713         }
714     }
715
716 #ifdef TEST
717     if( p->bufferVBO[VBOVcolours] || pvc ) {
718       glDisable(GL_COLOR_MATERIAL);
719       TelResetMaterial();
720     }
721 #endif
722
723     if( p->bufferVBO[VBOVertices] || p->vertices )
724       glDisableClientState(GL_VERTEX_ARRAY);
725     if( p->bufferVBO[VBOVcolours] || p->vcolours )
726       glDisableClientState(GL_COLOR_ARRAY);
727     if( p->bufferVBO[VBOVnormals] || p->vnormals )
728       glDisableClientState(GL_NORMAL_ARRAY);
729     if ( (p->bufferVBO[VBOVtexels] && !ForbidSetTextureMapping ) || p->vtexels )
730       glDisableClientState(GL_TEXTURE_COORD_ARRAY);
731
732     if ( g_nDegenerateModel ){
733       if(draw_mode <= GL_LINE_STRIP)
734         glPopAttrib();
735       return;
736     }
737   }
738
739   if( edge_flag || g_nDegenerateModel ) 
740     switch ( g_nDegenerateModel ) {
741       default: /* XXX_TDM_NODE or TINY */
742           /*
743             On some NVIDIA graphic cards, using glEdgeFlagPointer() in 
744             combination with VBO ( edge flag data put into a VBO buffer)
745             leads to a crash in a driver. Therefore, edge flags are simply 
746             igonored when VBOs are enabled, so all the edges are drawn if 
747             edge visibility is turned on. In order to draw edges selectively, 
748             either disable VBO or turn off edge visibilty in the current 
749             primitive array and create a separate primitive array (segments) 
750             and put edges to be drawn into it.
751           */
752           draw_edges ( p, edge_flag ? edge_colour : interior_colour );
753         break;
754         // DegenerateModel(as Lines, Points, BBoxs) are used only without VBO
755           case 2:  /* XXX_TDM_WIREFRAME */
756             if( p->VBOEnabled == 0 )
757               draw_degenerates_as_lines ( p, edge_flag ? edge_colour : interior_colour );
758             break;
759           case 3:  /* XXX_TDM_MARKER */
760             if( p->VBOEnabled == 0  )
761               draw_degenerates_as_points ( p, edge_flag ? edge_colour : interior_colour );
762             break;
763           case 4:  /* XXX_TDM_BBOX */
764             if( p->VBOEnabled == 0  )
765               draw_degenerates_as_bboxs ( p, edge_flag ? edge_colour : interior_colour  );
766             break;
767    }
768
769   if(draw_mode <= GL_LINE_STRIP)
770     glPopAttrib();
771 }
772
773 /*----------------------------------------------------------------------*/
774
775 static  TStatus
776 ParrayDelete( TSM_ELEM_DATA data, Tint n, cmn_key *k )
777 {
778   call_def_parray p = (call_def_parray)data.pdata;
779   if( p->VBOEnabled == VBO_OK ) {
780     OpenGl_ResourceCleaner* resCleaner = OpenGl_ResourceCleaner::GetInstance();
781     if( p->bufferVBO[VBOEdges] )
782       resCleaner->AddResource( (GLCONTEXT)p->contextId, new OpenGl_ResourceVBO(p->bufferVBO[VBOEdges]) ); 
783     if( p->bufferVBO[VBOVertices] )
784       resCleaner->AddResource( (GLCONTEXT)p->contextId, new OpenGl_ResourceVBO(p->bufferVBO[VBOVertices]) ); 
785     if( p->bufferVBO[VBOVcolours] )
786           resCleaner->AddResource( (GLCONTEXT)p->contextId, new OpenGl_ResourceVBO(p->bufferVBO[VBOVcolours]) ); 
787     if( p->bufferVBO[VBOVnormals] )
788       resCleaner->AddResource( (GLCONTEXT)p->contextId, new OpenGl_ResourceVBO(p->bufferVBO[VBOVnormals]) ); 
789     if( p->bufferVBO[VBOVtexels] )
790       resCleaner->AddResource( (GLCONTEXT)p->contextId, new OpenGl_ResourceVBO(p->bufferVBO[VBOVtexels]) ); 
791   }
792
793   return TSuccess;
794 }
795
796 /*----------------------------------------------------------------------*/
797
798 static void
799 draw_edges ( call_def_parray p, tel_colour edge_colour )
800 {
801   Tint    i, j, n;
802   Tint    edge_type=0, line_type_preserve=0;
803   Tfloat  edge_width=0, line_width_preserve=0; 
804   /* GLboolean texture_on;*/
805
806   GLint renderMode;
807   
808   LightOff();
809  
810   if( draw_mode > GL_LINE_STRIP ) { 
811     CMN_KEY k, k1, k2, k3, k4;
812
813     k1.id  = TelPolylineWidth;
814     k2.id  = TelPolylineType;
815     k3.id  = TelEdgeType;
816     k4.id  = TelEdgeWidth;
817     
818     TsmGetAttri( 4, &k1, &k2, &k3, &k4 );
819     
820     line_width_preserve = k1.data.fdata;
821     line_type_preserve  = k2.data.ldata;
822     edge_type           = k3.data.ldata;
823     edge_width          = k4.data.fdata;
824
825     if( line_width_preserve != edge_width ) {
826       k.id = TelPolylineWidth;
827       k.data.fdata = edge_width;
828       TsmSetAttri( 1, &k );
829     }
830     if( line_type_preserve != edge_type ) {
831       k.id = TelPolylineType;
832       k.data.ldata = edge_type;
833       TsmSetAttri( 1, &k );
834     }
835
836     glPushAttrib( GL_POLYGON_BIT );
837     glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); 
838   }
839
840   // OCC22236 NOTE: draw edges for all situations:
841   // 1) draw elements with GL_LINE style as edges from p->bufferVBO[VBOEdges] indicies array
842   // 2) draw elements from vertice array, when bounds defines count of primitive's verts.
843   // 3) draw primitive's edges by vertexes if no edges and bounds array is specified
844   if(p->flagBufferVBO == VBO_OK)
845   { 
846     glVBOBindBufferARB( GL_ARRAY_BUFFER_ARB, p->bufferVBO[VBOVertices] );
847     glEnableClientState( GL_VERTEX_ARRAY );
848     glColor3fv( edge_colour->rgb );
849     if ( p->num_edges > 0 && p->bufferVBO[VBOEdges] ) {
850       glVBOBindBufferARB(GL_ELEMENTS_ARRAY_BUFFER_ARB, p->bufferVBO[VBOEdges]); 
851       
852       // draw primitives by vertex count with the indicies
853       if( p->num_bounds > 0 ) {
854         Tint* offset = 0;
855         for( i = 0, offset = 0 ; i < p->num_bounds ; i++ ) {
856           glDrawElements( draw_mode, p->bounds[i], GL_UNSIGNED_INT, offset);
857           offset += p->bounds[i];
858         }
859       }
860       // draw one (or sequential) primitive by the indicies
861       else {
862         glDrawElements( draw_mode, p->num_edges , GL_UNSIGNED_INT, 0);
863       }
864     }
865     else if( p->num_bounds > 0 ) {
866       for( i = n = 0 ; i < p->num_bounds ; i ++ ){
867         glDrawArrays( draw_mode, n, p->bounds[i]);
868         n += p->bounds[i];
869       }
870     }
871     else {
872       glDrawArrays( draw_mode, 0, p->num_vertexs);
873     }
874
875     // unbind buffers
876     glDisableClientState(GL_VERTEX_ARRAY);
877     glVBOBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
878     glVBOBindBufferARB(GL_ELEMENTS_ARRAY_BUFFER_ARB, 0); 
879   }
880   else {
881
882     glEnableClientState(GL_VERTEX_ARRAY);
883     glVertexPointer(3, GL_FLOAT, 0, p->vertices); /* array of vertices  */
884 #ifdef OGLBUG
885       if( p->edge_vis ) {
886         glEnableClientState(GL_EDGE_FLAG_ARRAY);
887         glEdgeFlagPointer( sizeof(Tchar), p->edge_vis);
888       } else
889         glDisableClientState(GL_EDGE_FLAG_ARRAY);
890 #endif
891
892    glGetIntegerv( GL_RENDER_MODE, &renderMode );
893
894       glColor3fv( edge_colour->rgb );
895       if( p->num_bounds > 0 ) {
896         if( p->num_edges > 0 ) {
897           for( i=n=0 ; i<p->num_bounds ; i++ ) {
898 #ifndef OGLBUG
899             if( p->edge_vis ) {
900               glBegin( draw_mode );
901               for( j=0 ; j<p->bounds[i] ; j++ ) {
902                 glEdgeFlag( p->edge_vis[n+j] );
903                 glVertex3fv( &p->vertices[p->edges[n+j]].xyz[0] );
904               }
905               glEnd();
906             } else
907 #endif
908         if( renderMode == GL_FEEDBACK )
909           draw_primitive_elements( p, draw_mode, p->bounds[i], 
910                                   GL_UNSIGNED_INT, (GLenum*)&p->edges[n]);
911         else
912           glDrawElements( draw_mode, p->bounds[i], 
913                                   GL_UNSIGNED_INT, &p->edges[n]);
914             n += p->bounds[i];
915           }
916         } else {
917           for( i=n=0 ; i<p->num_bounds ; i++ ) {
918         if( renderMode == GL_FEEDBACK )
919           draw_primitive_array( p, draw_mode, n, p->bounds[i]);
920         else
921           glDrawArrays( draw_mode, n, p->bounds[i]);
922             n += p->bounds[i];
923           }
924         }
925       } 
926       else if( p->num_edges > 0 ) {
927 #ifndef OGLBUG
928         if( p->edge_vis ) {
929           glBegin( draw_mode );
930           for( i=0 ; i<p->num_edges ; i++ ) {
931             glEdgeFlag( p->edge_vis[i] );
932             glVertex3fv( &p->vertices[p->edges[i]].xyz[0] );
933           }
934           glEnd();
935         } else
936 #endif
937       if( renderMode == GL_FEEDBACK )
938         draw_primitive_elements( p, draw_mode, p->num_edges, 
939                                   GL_UNSIGNED_INT,(GLenum*) p->edges);
940       else
941         glDrawElements( draw_mode, p->num_edges, 
942                                   GL_UNSIGNED_INT, p->edges);
943       } else {
944       if( renderMode == GL_FEEDBACK )
945         draw_primitive_array( p, draw_mode, 0, p->num_vertexs);
946       else
947         glDrawArrays( draw_mode, 0, p->num_vertexs);
948       }
949     }
950
951   if( draw_mode > GL_LINE_STRIP ) {
952     CMN_KEY k;
953     if( line_width_preserve != edge_width ) {
954       k.id = TelPolylineWidth;
955       k.data.fdata = line_width_preserve;
956       TsmSetAttri( 1, &k );
957     }
958     if( line_type_preserve != edge_type ) {
959       k.id = TelPolylineType;
960       k.data.ldata = line_type_preserve;
961       TsmSetAttri( 1, &k );
962     }
963     glPopAttrib();
964   }
965 }
966
967 /*----------------------------------------------------------------------*/
968 static void draw_degenerates_points_as_points ( call_def_parray p ) { 
969
970   Tint       j;
971   tel_point  pv = p -> vertices;
972
973 #ifdef FULL_DEGENER
974   if ( g_fSkipRatio == 1. )
975     return;
976 #endif
977
978   for ( j=0 ; j<p->num_vertexs ; j++ ) {
979     glVertex3fv ( &pv[j].xyz[0] );
980   }
981 }  
982
983 /*----------------------------------------------------------------------*/
984 static void draw_degenerates_lines_as_points ( call_def_parray p ) { 
985
986   Tint       j;
987   GLfloat    pt[ 3 ];
988   tel_point  pv = p -> vertices;
989
990 #ifdef FULL_DEGENER
991   if ( g_fSkipRatio == 1. )
992     return;
993 #endif
994
995   for ( j=0 ; j<p->num_vertexs ; j+=2 ) {
996     pt[0] = pt[1] = pt[2] = 0.;
997     pt[ 0 ] += pv[j].xyz[ 0 ];
998     pt[ 1 ] += pv[j].xyz[ 1 ];
999     pt[ 2 ] += pv[j].xyz[ 2 ];
1000     pt[ 0 ] += pv[j+1].xyz[ 0 ];
1001     pt[ 1 ] += pv[j+1].xyz[ 1 ];
1002     pt[ 2 ] += pv[j+1].xyz[ 2 ];
1003     pt[ 0 ] /= 2;
1004     pt[ 1 ] /= 2;
1005     pt[ 2 ] /= 2;
1006     glVertex3fv ( pt );
1007   }
1008 }  
1009
1010 /*----------------------------------------------------------------------*/
1011 static void draw_degenerates_triangles_as_points ( call_def_parray p ) { 
1012
1013   Tint       i, j, iv;
1014   GLfloat    pt[ 3 ];
1015   tel_point  pv = p -> vertices;
1016
1017 #ifdef FULL_DEGENER
1018   if ( g_fSkipRatio == 1. )
1019     return;
1020 #endif
1021
1022   if( p->num_edges > 0 ) {
1023     for ( j=0 ; j<p->num_edges ; j+=3 ) {
1024       pt[0] = pt[1] = pt[2] = 0.;
1025       for ( i=0 ; i<3 ; i++ ) {
1026         iv = p->edges[j+i];
1027         pt[ 0 ] += pv[iv].xyz[ 0 ];
1028         pt[ 1 ] += pv[iv].xyz[ 1 ];
1029         pt[ 2 ] += pv[iv].xyz[ 2 ];
1030       }
1031       pt[ 0 ] /= 3;
1032       pt[ 1 ] /= 3;
1033       pt[ 2 ] /= 3;
1034       glVertex3fv ( pt );
1035     }
1036   } else {
1037     for ( j=0 ; j<p->num_vertexs ; j+=3 ) {
1038       pt[0] = pt[1] = pt[2] = 0.;
1039       for ( i=0 ; i<3 ; i++ ) {
1040         pt[ 0 ] += pv[j+i].xyz[ 0 ];
1041         pt[ 1 ] += pv[j+i].xyz[ 1 ];
1042         pt[ 2 ] += pv[j+i].xyz[ 2 ];
1043       }
1044       pt[ 0 ] /= 3;
1045       pt[ 1 ] /= 3;
1046       pt[ 2 ] /= 3;
1047       glVertex3fv ( pt );
1048     }
1049   }
1050 }  
1051
1052 /*----------------------------------------------------------------------*/
1053 static void draw_degenerates_trianglestrips_as_points ( call_def_parray p ) { 
1054
1055   Tint       i, j, k, n;
1056   GLfloat    pt[ 3 ];
1057   tel_point  pv = p -> vertices;
1058
1059 #ifdef FULL_DEGENER
1060   if ( g_fSkipRatio == 1. )
1061     return;
1062 #endif
1063
1064   if( p->num_bounds > 0 ) {
1065     for ( k=n=0 ; k<p->num_bounds ; k++ ) {
1066       for ( j=0 ; j<p->bounds[k]-2 ; j++ ) {
1067         pt[0] = pt[1] = pt[2] = 0.;
1068         for ( i=0 ; i<3 ; i++ ) {
1069           pt[ 0 ] += pv[n+j+i].xyz[ 0 ];
1070           pt[ 1 ] += pv[n+j+i].xyz[ 1 ];
1071           pt[ 2 ] += pv[n+j+i].xyz[ 2 ];
1072         }
1073         pt[ 0 ] /= 3;
1074         pt[ 1 ] /= 3;
1075         pt[ 2 ] /= 3;
1076         glVertex3fv ( pt );
1077       }
1078       n += p->bounds[k];
1079     }
1080   } else {
1081     for ( j=0 ; j<p->num_vertexs-2 ; j++ ) {
1082       pt[0] = pt[1] = pt[2] = 0.;
1083       for ( i=0 ; i<3 ; i++ ) {
1084         pt[ 0 ] += pv[j+i].xyz[ 0 ];
1085         pt[ 1 ] += pv[j+i].xyz[ 1 ];
1086         pt[ 2 ] += pv[j+i].xyz[ 2 ];
1087       }
1088       pt[ 0 ] /= 3;
1089       pt[ 1 ] /= 3;
1090       pt[ 2 ] /= 3;
1091       glVertex3fv ( pt );
1092     }
1093   }
1094 }  
1095
1096 /*----------------------------------------------------------------------*/
1097 static void draw_degenerates_polygons_as_points ( call_def_parray p ) { 
1098
1099   Tint       j, k, n, iv;
1100   GLfloat    pt[ 3 ];
1101   tel_point  pv = p -> vertices;
1102
1103 #ifdef FULL_DEGENER
1104   if ( g_fSkipRatio == 1. )
1105     return;
1106 #endif
1107
1108   if( p->num_bounds > 0 ) {
1109     if( p->num_edges > 0 ) {
1110       for ( k=n=0 ; k<p->num_bounds ; k++ ) {
1111         pt[0] = pt[1] = pt[2] = 0.;
1112         for ( j=0 ; j<p->bounds[k] ; j++ ) {
1113           iv = p->edges[n+j];
1114           pt[ 0 ] += pv[iv].xyz[ 0 ];
1115           pt[ 1 ] += pv[iv].xyz[ 1 ];
1116           pt[ 2 ] += pv[iv].xyz[ 2 ];
1117         }
1118         pt[ 0 ] /= p->bounds[k];
1119         pt[ 1 ] /= p->bounds[k];
1120         pt[ 2 ] /= p->bounds[k];
1121         glVertex3fv ( pt );
1122         n += p->bounds[k];
1123       }
1124     } else {  
1125       for ( k=n=0 ; k<p->num_bounds ; k++ ) {
1126         pt[0] = pt[1] = pt[2] = 0.;
1127         for ( j=0 ; j<p->bounds[k] ; j++ ) {
1128           pt[ 0 ] += pv[n+j].xyz[ 0 ];
1129           pt[ 1 ] += pv[n+j].xyz[ 1 ];
1130           pt[ 2 ] += pv[n+j].xyz[ 2 ];
1131         }
1132         pt[ 0 ] /= p->bounds[k];
1133         pt[ 1 ] /= p->bounds[k];
1134         pt[ 2 ] /= p->bounds[k];
1135         glVertex3fv ( pt );
1136         n += p->bounds[k];
1137       }
1138     }
1139   } else if( p->num_edges > 0 ) {
1140     pt[0] = pt[1] = pt[2] = 0.;
1141     for ( j=0 ; j<p->num_edges ; j++ ) {
1142       iv = p->edges[j];
1143       pt[ 0 ] += pv[iv].xyz[ 0 ];
1144       pt[ 1 ] += pv[iv].xyz[ 1 ];
1145       pt[ 2 ] += pv[iv].xyz[ 2 ];
1146     }
1147     pt[ 0 ] /= p->num_edges;
1148     pt[ 1 ] /= p->num_edges;
1149     pt[ 2 ] /= p->num_edges;
1150     glVertex3fv ( pt );
1151   } else {
1152     pt[0] = pt[1] = pt[2] = 0.;
1153     for ( j=0 ; j<p->num_vertexs ; j++ ) {
1154       pt[ 0 ] += pv[j].xyz[ 0 ];
1155       pt[ 1 ] += pv[j].xyz[ 1 ];
1156       pt[ 2 ] += pv[j].xyz[ 2 ];
1157     }
1158     pt[ 0 ] /= p->num_vertexs;
1159     pt[ 1 ] /= p->num_vertexs;
1160     pt[ 2 ] /= p->num_vertexs;
1161     glVertex3fv ( pt );
1162   }
1163 }  
1164
1165 /*----------------------------------------------------------------------*/
1166 static void draw_degenerates_quadrangles_as_points ( call_def_parray p ) { 
1167
1168   Tint       i, j, iv;
1169   GLfloat    pt[ 3 ];
1170   tel_point  pv = p -> vertices;
1171
1172 #ifdef FULL_DEGENER
1173   if ( g_fSkipRatio == 1. )
1174     return;
1175 #endif
1176
1177   if( p->num_edges > 0 ) {
1178     for ( j=0 ; j<p->num_edges ; j+=4 ) {
1179       pt[0] = pt[1] = pt[2] = 0.;
1180       for ( i=0 ; i<4 ; i++ ) {
1181         iv = p->edges[j+i];
1182         pt[ 0 ] += pv[iv].xyz[ 0 ];
1183         pt[ 1 ] += pv[iv].xyz[ 1 ];
1184         pt[ 2 ] += pv[iv].xyz[ 2 ];
1185       }
1186       pt[ 0 ] /= 4;
1187       pt[ 1 ] /= 4;
1188       pt[ 2 ] /= 4;
1189       glVertex3fv ( pt );
1190     }
1191   } else {
1192     for ( j=0 ; j<p->num_vertexs ; j+=4 ) {
1193       pt[0] = pt[1] = pt[2] = 0.;
1194       for ( i=0 ; i<4 ; i++ ) {
1195         pt[ 0 ] += pv[j+i].xyz[ 0 ];
1196         pt[ 1 ] += pv[j+i].xyz[ 1 ];
1197         pt[ 2 ] += pv[j+i].xyz[ 2 ];
1198       }
1199       pt[ 0 ] /= 4;
1200       pt[ 1 ] /= 4;
1201       pt[ 2 ] /= 4;
1202       glVertex3fv ( pt );
1203     }
1204   }
1205 }  
1206
1207 /*----------------------------------------------------------------------*/
1208 static void draw_degenerates_quadranglestrips_as_points ( call_def_parray p ) { 
1209
1210   Tint       i, j, k, n;
1211   GLfloat    pt[ 3 ];
1212   tel_point  pv = p -> vertices;
1213
1214 #ifdef FULL_DEGENER
1215   if ( g_fSkipRatio == 1. )
1216     return;
1217 #endif
1218
1219   if( p->num_bounds > 0 ) {
1220     for ( k=n=0 ; k<p->num_bounds ; k++ ) {
1221       for ( j=0 ; j<p->bounds[k]-2 ; j+=2 ) {
1222         pt[0] = pt[1] = pt[2] = 0.;
1223         for ( i=0 ; i<4 ; i++ ) {
1224           pt[ 0 ] += pv[n+j+i].xyz[ 0 ];
1225           pt[ 1 ] += pv[n+j+i].xyz[ 1 ];
1226           pt[ 2 ] += pv[n+j+i].xyz[ 2 ];
1227         }
1228         pt[ 0 ] /= 4;
1229         pt[ 1 ] /= 4;
1230         pt[ 2 ] /= 4;
1231         glVertex3fv ( pt );
1232       }
1233       n += p->bounds[k];
1234     }
1235   } else {
1236     for ( j=0 ; j<p->num_vertexs-2 ; j+=2 ) {
1237       pt[0] = pt[1] = pt[2] = 0.;
1238       for ( i=0 ; i<4 ; i++ ) {
1239         pt[ 0 ] += pv[j+i].xyz[ 0 ];
1240         pt[ 1 ] += pv[j+i].xyz[ 1 ];
1241         pt[ 2 ] += pv[j+i].xyz[ 2 ];
1242       }
1243       pt[ 0 ] /= 4;
1244       pt[ 1 ] /= 4;
1245       pt[ 2 ] /= 4;
1246       glVertex3fv ( pt );
1247     }
1248   }
1249 }  
1250
1251 /*----------------------------------------------------------------------*/
1252 static void draw_degenerates_as_points ( call_def_parray p, 
1253                                         tel_colour edge_colour ) 
1254 {
1255
1256   GLboolean zbuff_state = glIsEnabled(GL_DEPTH_TEST);
1257   LightOff ();
1258   if( zbuff_state ) glDisable(GL_DEPTH_TEST); 
1259   glColor3fv( edge_colour->rgb );
1260   glBegin ( GL_POINTS );
1261   switch( draw_mode ) {
1262       case GL_POINTS:
1263         draw_degenerates_points_as_points( p );
1264         break;
1265       case GL_LINES:
1266         draw_degenerates_lines_as_points( p );
1267         break;
1268       case GL_LINE_STRIP:
1269       case GL_POLYGON:
1270         draw_degenerates_polygons_as_points( p );
1271         break;
1272       case GL_TRIANGLES:
1273         draw_degenerates_triangles_as_points( p );
1274         break;
1275       case GL_QUADS:
1276         draw_degenerates_quadrangles_as_points( p );
1277         break;
1278       case GL_TRIANGLE_FAN:
1279       case GL_TRIANGLE_STRIP:
1280         draw_degenerates_trianglestrips_as_points( p );
1281         break;
1282       case GL_QUAD_STRIP:
1283         draw_degenerates_quadranglestrips_as_points( p );
1284         break;
1285       default:
1286         break;
1287   }
1288
1289   glEnd ();
1290
1291   if( zbuff_state ) glEnable(GL_DEPTH_TEST); 
1292 }
1293
1294 /*----------------------------------------------------------------------*/
1295 static void draw_degenerates_lines_as_lines ( call_def_parray p ) { 
1296
1297   Tint       i,j,n,iv;
1298   tel_point  pv = p -> vertices;
1299
1300   n = p->num_vertexs;
1301   j = (int)((1.-g_fSkipRatio)*n);
1302   while ( j-- ) {
1303     i = OGL_Rand() % n;
1304     p->keys[i] = -p->keys[i];
1305   };
1306
1307   if( p->num_bounds > 0 ) {
1308     if( p->num_edges > 0 ) {
1309       for ( i=n=0 ; i<p->num_bounds ; i++ ) {
1310         glBegin ( GL_LINES );
1311         for ( j=0 ; j<p->bounds[i] ; j++ ) {
1312           iv = p->edges[n+j];
1313           if( p->keys[iv] < 0 ) {
1314             p->keys[iv] = -p->keys[iv];
1315             glVertex3fv ( pv[iv].xyz );
1316           }
1317         }
1318         glEnd();
1319         n += p->bounds[i];
1320       }
1321     } else {  
1322       for ( i=n=0 ; i<p->num_bounds ; i++ ) {
1323         glBegin ( GL_LINES );
1324         for ( j=0 ; j<p->bounds[i] ; j++ ) {
1325           if( p->keys[n+j] < 0 ) {
1326             p->keys[n+j] = -p->keys[n+j];
1327             glVertex3fv ( pv[n+j].xyz );
1328           }
1329         }
1330         glEnd();
1331         n += p->bounds[i];
1332       }
1333     }
1334   } else if( p->num_edges > 0 ) {
1335     glBegin ( GL_LINES );
1336     for ( j=0 ; j<p->num_edges ; j++ ) {
1337       iv = p->edges[j];
1338       if( p->keys[iv] < 0 ) {
1339         p->keys[iv] = -p->keys[iv];
1340         glVertex3fv ( pv[iv].xyz );
1341       }
1342     }
1343     glEnd();
1344   } else {
1345     glBegin ( GL_LINES );
1346     for ( j=0 ; j<p->num_vertexs ; j++ ) {
1347       if( p->keys[j] < 0 ) {
1348         p->keys[j] = -p->keys[j];
1349         glVertex3fv ( pv[j].xyz );
1350       }
1351     }
1352     glEnd();
1353   }
1354 }  
1355
1356 /*----------------------------------------------------------------------*/
1357 static void draw_degenerates_triangles_as_lines ( call_def_parray p ) 
1358
1359
1360   Tint       i,j,n,iv;
1361   tel_point  pv = p -> vertices;
1362
1363   n = p->num_vertexs/3;
1364   j = (int)((1.-g_fSkipRatio)*n);
1365   while ( j-- ) {
1366     i = OGL_Rand() % n; i *= 3;
1367     p->keys[i] = -p->keys[i];
1368   };
1369
1370   if( p->num_edges > 0 ) {
1371     for ( j=0 ; j<p->num_edges ; j+=3 ) {
1372       iv = p->edges[j];
1373       if( p->keys[iv] < 0 ) { 
1374         p->keys[iv] = -p->keys[iv];
1375         glBegin ( GL_LINE_LOOP );
1376         for ( i=0 ; i<3 ; i++ ) {
1377           iv = p->edges[j+i];
1378           glVertex3fv ( pv[iv].xyz );
1379         }
1380         glEnd();
1381       }
1382     }
1383   } else {
1384     for ( j=0 ; j<p->num_vertexs ; j+=3 ) {
1385       if( p->keys[j] < 0 ) { 
1386         p->keys[j] = -p->keys[j];
1387         glBegin ( GL_LINE_LOOP );
1388         for ( i=0 ; i<3 ; i++ ) {
1389           glVertex3fv ( pv[j+i].xyz );
1390         }
1391         glEnd();
1392       }
1393     }
1394   }
1395 }  
1396
1397 /*----------------------------------------------------------------------*/
1398 static void draw_degenerates_trianglestrips_as_lines ( call_def_parray p ) 
1399
1400
1401   Tint       i,j,k,n,ni;
1402   tel_point  pv = p -> vertices;
1403
1404   if( p->num_bounds > 0 ) {
1405     for ( i=n=0 ; i<p->num_bounds ; i++ ) {
1406       ni = p->bounds[i]-2;
1407       k = (int)((1.-g_fSkipRatio)*ni);
1408       while ( k-- ) {
1409         j = OGL_Rand() % ni; j += 2;
1410         p->keys[n+j] = -p->keys[n+j];
1411       };
1412       for ( j=2 ; j<p->bounds[i] ; j++ ) {
1413         if( p->keys[n+j] < 0 ) { 
1414           p->keys[n+j] = -p->keys[n+j];
1415           glBegin ( GL_LINE_LOOP );
1416           glVertex3fv ( pv[n+j-2].xyz );
1417           glVertex3fv ( pv[n+j-1].xyz );
1418           glVertex3fv ( pv[n+j].xyz );
1419           glEnd();
1420         }
1421       }
1422       n += p->bounds[i];
1423     }
1424   } else {
1425     ni = p->num_vertexs-2;
1426     k = (int)((1.-g_fSkipRatio)*ni);
1427     while ( k-- ) {
1428       j = OGL_Rand() % ni; j += 2;
1429       p->keys[j] = -p->keys[j];
1430     };
1431     for ( j=2 ; j<p->num_vertexs ; j++ ) {
1432       if( p->keys[j] < 0 ) { 
1433         p->keys[j] = -p->keys[j];
1434         glBegin ( GL_LINE_LOOP );
1435         glVertex3fv ( pv[j-2].xyz );
1436         glVertex3fv ( pv[j-1].xyz );
1437         glVertex3fv ( pv[j].xyz );
1438         glEnd();
1439       }
1440     }
1441   }
1442 }  
1443
1444 /*----------------------------------------------------------------------*/
1445 static void draw_degenerates_polygons_as_lines ( call_def_parray p )
1446
1447   Tint       i,j,n,iv;
1448   tel_point  pv = p -> vertices;
1449
1450   n = p->num_vertexs;
1451   j = (int)((1.-g_fSkipRatio)*n);
1452   while ( j-- ) {
1453     i = OGL_Rand() % n;
1454     p->keys[i] = -p->keys[i];
1455   };
1456
1457   if( p->num_bounds > 0 ) {
1458     if( p->num_edges > 0 ) {
1459       for ( i=n=0 ; i<p->num_bounds ; i++ ) {
1460         glBegin ( GL_LINE_LOOP );
1461         for ( j=0 ; j<p->bounds[i] ; j++ ) {
1462           iv = p->edges[n+j];
1463           if( p->keys[iv] < 0 ) {
1464             p->keys[iv] = -p->keys[iv];
1465             glVertex3fv ( pv[iv].xyz );
1466           }
1467         }
1468         glEnd();
1469         n += p->bounds[i];
1470       }
1471     } else {  
1472       for ( i=n=0 ; i<p->num_bounds ; i++ ) {
1473         glBegin ( GL_LINE_LOOP );
1474         for ( j=0 ; j<p->bounds[i] ; j++ ) {
1475           if( p->keys[n+j] < 0 ) {
1476             p->keys[n+j] = -p->keys[n+j];
1477             glVertex3fv ( pv[n+j].xyz );
1478           }
1479         }
1480         glEnd();
1481         n += p->bounds[i];
1482       }
1483     }
1484   } else if( p->num_edges > 0 ) {
1485     glBegin ( GL_LINE_LOOP );
1486     for ( j=0 ; j<p->num_edges ; j++ ) {
1487       iv = p->edges[j];
1488       if( p->keys[iv] < 0 ) {
1489         p->keys[iv] = -p->keys[iv];
1490         glVertex3fv ( pv[iv].xyz );
1491       }
1492     }
1493     glEnd();
1494   } else {
1495     glBegin ( GL_LINE_LOOP );
1496     for ( j=0 ; j<p->num_vertexs ; j++ ) {
1497       if( p->keys[j] < 0 ) {
1498         p->keys[j] = -p->keys[j];
1499         glVertex3fv ( pv[j].xyz );
1500       }
1501     }
1502     glEnd();
1503   }
1504
1505 }  
1506
1507 /*----------------------------------------------------------------------*/
1508 static void draw_degenerates_quadrangles_as_lines ( call_def_parray p ) 
1509
1510
1511   Tint       i,j,n,iv;
1512   tel_point  pv = p -> vertices;
1513
1514   n = p->num_vertexs/4;
1515   j = (int)((1.-g_fSkipRatio)*n);
1516   while ( j-- ) {
1517     i = OGL_Rand() % n; i *= 4;
1518     p->keys[i] = -p->keys[i];
1519   };
1520
1521   if( p->num_edges > 0 ) {
1522     for ( j=0 ; j<p->num_edges ; j+=4 ) {
1523       iv = p->edges[j];
1524       if( p->keys[iv] < 0 ) {
1525         p->keys[iv] = -p->keys[iv];
1526         glBegin ( GL_LINE_LOOP );
1527         for ( i=0 ; i<4 ; i++ ) {
1528           iv = p->edges[j+i];
1529           glVertex3fv ( pv[iv].xyz );
1530         }
1531         glEnd();
1532       }
1533     }
1534   } else {
1535     for ( j=0 ; j<p->num_vertexs ; j+=4 ) {
1536       if( p->keys[j] < 0 ) {
1537         p->keys[j] = -p->keys[j];
1538         glBegin ( GL_LINE_LOOP );
1539         for ( i=0 ; i<4 ; i++ ) {
1540           glVertex3fv ( pv[j+i].xyz );
1541         }
1542         glEnd();
1543       }
1544     }
1545   }
1546 }  
1547
1548 /*----------------------------------------------------------------------*/
1549 static void draw_degenerates_quadranglestrips_as_lines ( call_def_parray p )
1550
1551
1552   Tint       i,j,k,n,ni;
1553   tel_point  pv = p -> vertices;
1554
1555   if( p->num_bounds > 0 ) {
1556     for ( i=n=0 ; i<p->num_bounds ; i++ ) {
1557       ni = p->bounds[i]/2-2;
1558       k = (int)((1.-g_fSkipRatio)*ni);
1559       while ( k-- ) {
1560         j = OGL_Rand() % ni; j = j*2+2;
1561         p->keys[n+j] = -p->keys[n+j];
1562       };
1563       for ( j=3 ; j<p->bounds[i] ; j+=2 ) {
1564         if( p->keys[n+j] < 0 ) {
1565           p->keys[n+j] = -p->keys[n+j];
1566           glBegin ( GL_LINE_LOOP );
1567           glVertex3fv ( pv[n+j-3].xyz );
1568           glVertex3fv ( pv[n+j-2].xyz );
1569           glVertex3fv ( pv[n+j-1].xyz );
1570           glVertex3fv ( pv[n+j].xyz );
1571           glEnd();
1572         }
1573       }
1574       n += p->bounds[i];
1575     }
1576   } else {
1577     ni = p->num_vertexs/2-2;
1578     k = (int)((1.-g_fSkipRatio)*ni);
1579     while ( k-- ) {
1580       j = OGL_Rand() % ni; j = j*2+2;
1581       p->keys[j] = -p->keys[j];
1582     };
1583     for ( j=3 ; j<p->num_vertexs ; j+=2 ) {
1584       if( p->keys[j] < 0 ) {
1585         p->keys[j] = -p->keys[j];
1586         glBegin ( GL_LINE_LOOP );
1587         glVertex3fv ( pv[j-3].xyz );
1588         glVertex3fv ( pv[j-2].xyz );
1589         glVertex3fv ( pv[j-1].xyz );
1590         glVertex3fv ( pv[j].xyz );
1591         glEnd();
1592       }
1593     }
1594   }
1595 }  
1596
1597 /*----------------------------------------------------------------------*/
1598 static void draw_degenerates_as_lines ( call_def_parray p, 
1599                                        tel_colour edge_colour )
1600 {
1601
1602   GLint renderMode;
1603
1604   GLboolean zbuff_state = glIsEnabled(GL_DEPTH_TEST);
1605
1606   LightOff ();
1607
1608   if( zbuff_state ) glDisable(GL_DEPTH_TEST); 
1609
1610   glColor3fv( edge_colour->rgb );
1611
1612   if( g_fSkipRatio != 0 ) switch( draw_mode ) {
1613       case GL_POINTS:
1614         draw_degenerates_points_as_points( p );
1615         break;
1616       case GL_LINES:
1617         draw_degenerates_lines_as_lines( p );
1618         break;
1619       case GL_LINE_STRIP:
1620       case GL_POLYGON:
1621         draw_degenerates_polygons_as_lines( p );
1622         break;
1623       case GL_TRIANGLES:
1624         draw_degenerates_triangles_as_lines( p );
1625         break;
1626       case GL_QUADS:
1627         draw_degenerates_quadrangles_as_lines( p );
1628         break;
1629       case GL_TRIANGLE_FAN:
1630       case GL_TRIANGLE_STRIP:
1631         draw_degenerates_trianglestrips_as_lines( p );
1632         break;
1633       case GL_QUAD_STRIP:
1634         draw_degenerates_quadranglestrips_as_lines( p );
1635         break;
1636       default:
1637         break;
1638   }
1639   else {
1640     int i,n;
1641
1642 #ifdef OCC3192
1643     GLboolean color_array_mode, 
1644       edge_flag_array_mode,
1645       index_array_mode,
1646       normal_array_mode,
1647       texture_coord_array_mode,
1648       vertex_array_mode;
1649 #endif
1650     glPushAttrib( GL_POLYGON_BIT );
1651     glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
1652
1653 #ifdef OCC3192
1654     color_array_mode         = glIsEnabled( GL_COLOR_ARRAY );
1655     edge_flag_array_mode     = glIsEnabled( GL_EDGE_FLAG_ARRAY );
1656     index_array_mode         = glIsEnabled( GL_INDEX_ARRAY );
1657     normal_array_mode        = glIsEnabled( GL_NORMAL_ARRAY );
1658     texture_coord_array_mode = glIsEnabled( GL_TEXTURE_COORD_ARRAY );
1659     vertex_array_mode        = glIsEnabled( GL_VERTEX_ARRAY );
1660
1661     glDisableClientState( GL_COLOR_ARRAY );
1662     glDisableClientState( GL_EDGE_FLAG_ARRAY );
1663     glDisableClientState( GL_INDEX_ARRAY );
1664     glDisableClientState( GL_NORMAL_ARRAY );
1665     glDisableClientState( GL_TEXTURE_COORD_ARRAY );
1666
1667     if( !vertex_array_mode ) glEnableClientState( GL_VERTEX_ARRAY );
1668 #else
1669     glEnableClientState( GL_VERTEX_ARRAY );
1670 #endif
1671     glVertexPointer(3, GL_FLOAT, 0, p->vertices); /* array of vertices  */
1672
1673     glGetIntegerv( GL_RENDER_MODE, &renderMode );
1674
1675     if( p->num_bounds > 0 ) {
1676       if( p->num_edges > 0 ) {
1677         for( i=n=0 ; i<p->num_bounds ; i++ ) {
1678           if( renderMode == GL_FEEDBACK )
1679             draw_primitive_elements( p, draw_mode, p->bounds[i], 
1680             GL_UNSIGNED_INT, (GLenum*) &p->edges[n]);
1681           else
1682             glDrawElements( draw_mode, p->bounds[i],
1683             GL_UNSIGNED_INT, &p->edges[n]);
1684           n += p->bounds[i];
1685         }
1686       } else {
1687         for( i=n=0 ; i<p->num_bounds ; i++ ) {
1688           if( renderMode == GL_FEEDBACK )
1689             draw_primitive_array( p, draw_mode, n, p->bounds[i]);
1690           else
1691             glDrawArrays( draw_mode, n, p->bounds[i]);
1692           n += p->bounds[i];
1693         }
1694       }
1695     } else if( p->num_edges > 0 ) {
1696       if( renderMode == GL_FEEDBACK )
1697         draw_primitive_elements( p, draw_mode, p->num_edges, 
1698         GL_UNSIGNED_INT, (GLenum*) p->edges);
1699       else
1700         glDrawElements( draw_mode, p->num_edges,
1701         GL_UNSIGNED_INT, p->edges);
1702     } else {
1703       if( renderMode == GL_FEEDBACK )
1704         draw_primitive_array( p, draw_mode, 0, p->num_vertexs);
1705       else
1706         glDrawArrays( draw_mode, 0, p->num_vertexs);
1707     }
1708
1709 #ifdef OCC3192
1710     if( !vertex_array_mode ) glDisableClientState( GL_VERTEX_ARRAY );
1711
1712     if( color_array_mode )         glEnableClientState( GL_COLOR_ARRAY );
1713     if( edge_flag_array_mode )     glEnableClientState( GL_EDGE_FLAG_ARRAY );
1714     if( index_array_mode )         glEnableClientState( GL_INDEX_ARRAY );
1715     if( normal_array_mode )        glEnableClientState( GL_NORMAL_ARRAY );
1716     if( texture_coord_array_mode ) glEnableClientState( GL_TEXTURE_COORD_ARRAY );
1717 #endif
1718     glPopAttrib();
1719   }
1720
1721   if( zbuff_state ) glEnable(GL_DEPTH_TEST); 
1722
1723 }  
1724
1725 static void draw_degenerates_as_bboxs ( call_def_parray p, 
1726                                         tel_colour edge_colour )
1727 {
1728
1729   Tint      i;
1730   GLfloat   minp[ 3 ] = { FLT_MAX, FLT_MAX, FLT_MAX };
1731   GLfloat   maxp[ 3 ] = { FLT_MIN, FLT_MIN, FLT_MIN };
1732   tel_point pv = p -> vertices;
1733
1734   LightOff ();
1735
1736   glColor3fv( edge_colour->rgb );
1737
1738   for ( i=0 ; i<p->num_vertexs ; ++i ) {
1739     if ( pv[  i  ].xyz[ 0 ] < minp[ 0 ] )
1740       minp[ 0 ] = pv[  i  ].xyz[ 0 ] ;
1741     if ( pv[  i  ].xyz[ 1 ] < minp[ 1 ] )
1742       minp[ 1 ] = pv[  i  ].xyz[ 1 ] ;
1743     if ( pv[  i  ].xyz[ 2 ] < minp[ 2 ] )
1744       minp[ 2 ] = pv[  i  ].xyz[ 2 ] ;
1745
1746     if ( pv[  i  ].xyz[ 0 ] > maxp[ 0 ] )
1747       maxp[ 0 ] = pv[  i  ].xyz[ 0 ] ;
1748     if ( pv[  i  ].xyz[ 1 ] > maxp[ 1 ] )
1749       maxp[ 1 ] = pv[  i  ].xyz[ 1 ] ;
1750     if ( pv[  i ].xyz[ 2 ] > maxp[ 2 ] )
1751       maxp[ 2 ] = pv[  i  ].xyz[ 2 ] ;
1752   }  /* end for ( i ) */
1753
1754   glBegin ( GL_LINE_STRIP );
1755
1756   glVertex3fv ( minp );
1757   glVertex3f ( minp[ 0 ], maxp[ 1 ], minp[ 2 ] );
1758   glVertex3f ( minp[ 0 ], maxp[ 1 ], maxp[ 2 ] );
1759   glVertex3f ( minp[ 0 ], minp[ 1 ], maxp[ 2 ] );
1760   glVertex3f ( minp[ 0 ], minp[ 1 ], minp[ 2 ] );
1761
1762   glVertex3f ( maxp[ 0 ], minp[ 1 ], minp[ 2 ] );
1763   glVertex3f ( maxp[ 0 ], maxp[ 1 ], minp[ 2 ] );
1764   glVertex3f ( maxp[ 0 ], maxp[ 1 ], maxp[ 2 ] );
1765   glVertex3f ( maxp[ 0 ], minp[ 1 ], maxp[ 2 ] );
1766   glVertex3f ( maxp[ 0 ], minp[ 1 ], minp[ 2 ] );
1767
1768   glVertex3f ( maxp[ 0 ], minp[ 1 ], maxp[ 2 ] );
1769   glVertex3f ( minp[ 0 ], minp[ 1 ], maxp[ 2 ] );
1770   glVertex3f ( minp[ 0 ], maxp[ 1 ], maxp[ 2 ] );
1771   glVertex3fv ( maxp );
1772   glVertex3f ( maxp[ 0 ], maxp[ 1 ], minp[ 2 ] );
1773   glVertex3f ( minp[ 0 ], maxp[ 1 ], minp[ 2 ] );
1774
1775   glEnd();
1776
1777 }  /* end draw_degenerates_as_bboxs */