OCC22199 OpenGL memory leaks in TKOpenGl
[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     //end bindings
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         glDrawElements( draw_mode, p->num_edges , GL_UNSIGNED_INT, 0);
649       }
650       else {
651         for( i = n = 0 ; i < p->num_bounds ; i ++ ){
652           glDrawArrays( draw_mode, n, p->bounds[i]);
653           n += p->bounds[i];
654         }
655       }
656       //bind with 0
657       glVBOBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); 
658       glVBOBindBufferARB(GL_ELEMENTS_ARRAY_BUFFER_ARB, 0); 
659     } 
660     else {
661       if( p->num_bounds > 0 ) {
662         if( p->num_edges > 0 ) {
663             for( i=n=0 ; i<p->num_bounds ; i++ ) {
664               if( pfc ) glColor3fv  ( pfc[i].rgb  );
665               if( renderMode == GL_FEEDBACK )
666                 draw_primitive_elements( p, draw_mode, p->bounds[i], 
667                                         GL_UNSIGNED_INT,(GLenum*) &p->edges[n]);
668               else
669                 glDrawElements( draw_mode, p->bounds[i], 
670                                 GL_UNSIGNED_INT, &p->edges[n]);
671               n += p->bounds[i];
672             }
673         } else {
674           for( i=n=0 ; i<p->num_bounds ; i++ ) {
675                 if( pfc ) 
676                   glColor3fv  ( pfc[i].rgb  );
677                 if( renderMode == GL_FEEDBACK )
678                   draw_primitive_array( p, draw_mode, n, p->bounds[i]);
679                 else
680                 {
681                   glDrawArrays( draw_mode, n, p->bounds[i]);
682                 }
683                 n += p->bounds[i];
684               }
685             }
686       } else if( p->num_edges > 0 ) {
687           if( renderMode == GL_FEEDBACK )
688             draw_primitive_elements( p, draw_mode, p->num_edges, 
689                                     GL_UNSIGNED_INT,(GLenum*) &p->edges[0]);
690           else
691          glDrawElements( draw_mode, p->num_edges, GL_UNSIGNED_INT, p->edges);
692       } else {
693             if( renderMode == GL_FEEDBACK )
694             draw_primitive_array( p, draw_mode, 0, p->num_vertexs);
695           else
696             glDrawArrays( draw_mode, 0, p->num_vertexs);
697         }
698     }
699
700 #ifdef TEST
701     if( p->bufferVBO[VBOVcolours] || pvc ) {
702       glDisable(GL_COLOR_MATERIAL);
703       TelResetMaterial();
704     }
705 #endif
706
707     if( p->bufferVBO[VBOVertices] || p->vertices )
708       glDisableClientState(GL_VERTEX_ARRAY);
709     if( p->bufferVBO[VBOVcolours] || p->vcolours )
710       glDisableClientState(GL_COLOR_ARRAY);
711     if( p->bufferVBO[VBOVnormals] || p->vnormals )
712       glDisableClientState(GL_NORMAL_ARRAY);
713     if ( (p->bufferVBO[VBOVtexels] && !ForbidSetTextureMapping ) || p->vtexels )
714       glDisableClientState(GL_TEXTURE_COORD_ARRAY);
715
716     if ( g_nDegenerateModel ){
717       if(draw_mode <= GL_LINE_STRIP)
718         glPopAttrib();
719       return;
720     }
721   }
722
723   if( edge_flag || g_nDegenerateModel ) 
724     switch ( g_nDegenerateModel ) {
725       default: /* XXX_TDM_NODE or TINY */
726           /*
727             On some NVIDIA graphic cards, using glEdgeFlagPointer() in 
728             combination with VBO ( edge flag data put into a VBO buffer)
729             leads to a crash in a driver. Therefore, edge flags are simply 
730             igonored when VBOs are enabled, so all the edges are drawn if 
731             edge visibility is turned on. In order to draw edges selectively, 
732             either disable VBO or turn off edge visibilty in the current 
733             primitive array and create a separate primitive array (segments) 
734             and put edges to be drawn into it.
735           */
736           draw_edges ( p, edge_flag ? edge_colour : interior_colour );
737         break;
738         // DegenerateModel(as Lines, Points, BBoxs) are used only without VBO
739           case 2:  /* XXX_TDM_WIREFRAME */
740             if( p->VBOEnabled == 0 )
741               draw_degenerates_as_lines ( p, edge_flag ? edge_colour : interior_colour );
742             break;
743           case 3:  /* XXX_TDM_MARKER */
744             if( p->VBOEnabled == 0  )
745               draw_degenerates_as_points ( p, edge_flag ? edge_colour : interior_colour );
746             break;
747           case 4:  /* XXX_TDM_BBOX */
748             if( p->VBOEnabled == 0  )
749               draw_degenerates_as_bboxs ( p, edge_flag ? edge_colour : interior_colour  );
750             break;
751    }
752
753   if(draw_mode <= GL_LINE_STRIP)
754     glPopAttrib();
755 }
756
757 /*----------------------------------------------------------------------*/
758
759 static  TStatus
760 ParrayDelete( TSM_ELEM_DATA data, Tint n, cmn_key *k )
761 {
762   call_def_parray p = (call_def_parray)data.pdata;
763   if( p->VBOEnabled == VBO_OK ) {
764     OpenGl_ResourceCleaner* resCleaner = OpenGl_ResourceCleaner::GetInstance();
765     if( p->bufferVBO[VBOEdges] )
766       resCleaner->AddResource( (GLCONTEXT)p->contextId, new OpenGl_ResourceVBO(p->bufferVBO[VBOEdges]) ); 
767     if( p->bufferVBO[VBOVertices] )
768       resCleaner->AddResource( (GLCONTEXT)p->contextId, new OpenGl_ResourceVBO(p->bufferVBO[VBOVertices]) ); 
769     if( p->bufferVBO[VBOVcolours] )
770           resCleaner->AddResource( (GLCONTEXT)p->contextId, new OpenGl_ResourceVBO(p->bufferVBO[VBOVcolours]) ); 
771     if( p->bufferVBO[VBOVnormals] )
772       resCleaner->AddResource( (GLCONTEXT)p->contextId, new OpenGl_ResourceVBO(p->bufferVBO[VBOVnormals]) ); 
773     if( p->bufferVBO[VBOVtexels] )
774       resCleaner->AddResource( (GLCONTEXT)p->contextId, new OpenGl_ResourceVBO(p->bufferVBO[VBOVtexels]) ); 
775   }
776
777   return TSuccess;
778 }
779
780 /*----------------------------------------------------------------------*/
781
782 static void
783 draw_edges ( call_def_parray p, tel_colour edge_colour )
784 {
785   Tint    i, j, n;
786   Tint    edge_type=0, line_type_preserve=0;
787   Tfloat  edge_width=0, line_width_preserve=0; 
788   /* GLboolean texture_on;*/
789
790   GLint renderMode;
791   
792   LightOff();
793  
794   if( draw_mode > GL_LINE_STRIP ) { 
795     CMN_KEY k, k1, k2, k3, k4;
796
797     k1.id  = TelPolylineWidth;
798     k2.id  = TelPolylineType;
799     k3.id  = TelEdgeType;
800     k4.id  = TelEdgeWidth;
801     
802     TsmGetAttri( 4, &k1, &k2, &k3, &k4 );
803     
804     line_width_preserve = k1.data.fdata;
805     line_type_preserve  = k2.data.ldata;
806     edge_type           = k3.data.ldata;
807     edge_width          = k4.data.fdata;
808
809     if( line_width_preserve != edge_width ) {
810       k.id = TelPolylineWidth;
811       k.data.fdata = edge_width;
812       TsmSetAttri( 1, &k );
813     }
814     if( line_type_preserve != edge_type ) {
815       k.id = TelPolylineType;
816       k.data.ldata = edge_type;
817       TsmSetAttri( 1, &k );
818     }
819
820     glPushAttrib( GL_POLYGON_BIT );
821     glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); 
822   }
823
824   // OCC22236 NOTE: draw edges for all situations:
825   // 1) draw elements with GL_LINE style as edges from p->bufferVBO[VBOEdges] indicies array
826   // 2) draw elements with GL_LINE style as edges from vertice array,
827   //    when bounds defines count of primitive's verts.
828   if(p->flagBufferVBO == VBO_OK)
829   { 
830     glVBOBindBufferARB( GL_ARRAY_BUFFER_ARB, p->bufferVBO[VBOVertices] );
831     glEnableClientState( GL_VERTEX_ARRAY );
832     glColor3fv( edge_colour->rgb );
833     if ( p->num_edges > 0 && p->bufferVBO[VBOEdges] ) {
834       glVBOBindBufferARB(GL_ELEMENTS_ARRAY_BUFFER_ARB, p->bufferVBO[VBOEdges]); 
835       glDrawElements( draw_mode, p->num_edges, GL_UNSIGNED_INT, 0);
836     }
837     else {
838       for( i = n = 0 ; i < p->num_bounds ; i ++ ) {
839         glDrawArrays( draw_mode , n , p->bounds[i]);
840         n += p->bounds[i];
841       }
842     }
843     glDisableClientState(GL_VERTEX_ARRAY);
844     glVBOBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
845     glVBOBindBufferARB(GL_ELEMENTS_ARRAY_BUFFER_ARB, 0); 
846   }
847   else {
848
849     glEnableClientState(GL_VERTEX_ARRAY);
850     glVertexPointer(3, GL_FLOAT, 0, p->vertices); /* array of vertices  */
851 #ifdef OGLBUG
852       if( p->edge_vis ) {
853         glEnableClientState(GL_EDGE_FLAG_ARRAY);
854         glEdgeFlagPointer( sizeof(Tchar), p->edge_vis);
855       } else
856         glDisableClientState(GL_EDGE_FLAG_ARRAY);
857 #endif
858
859    glGetIntegerv( GL_RENDER_MODE, &renderMode );
860
861       glColor3fv( edge_colour->rgb );
862       if( p->num_bounds > 0 ) {
863         if( p->num_edges > 0 ) {
864           for( i=n=0 ; i<p->num_bounds ; i++ ) {
865 #ifndef OGLBUG
866             if( p->edge_vis ) {
867               glBegin( draw_mode );
868               for( j=0 ; j<p->bounds[i] ; j++ ) {
869                 glEdgeFlag( p->edge_vis[n+j] );
870                 glVertex3fv( &p->vertices[p->edges[n+j]].xyz[0] );
871               }
872               glEnd();
873             } else
874 #endif
875         if( renderMode == GL_FEEDBACK )
876           draw_primitive_elements( p, draw_mode, p->bounds[i], 
877                                   GL_UNSIGNED_INT, (GLenum*)&p->edges[n]);
878         else
879           glDrawElements( draw_mode, p->bounds[i], 
880                                   GL_UNSIGNED_INT, &p->edges[n]);
881             n += p->bounds[i];
882           }
883         } else {
884           for( i=n=0 ; i<p->num_bounds ; i++ ) {
885         if( renderMode == GL_FEEDBACK )
886           draw_primitive_array( p, draw_mode, n, p->bounds[i]);
887         else
888           glDrawArrays( draw_mode, n, p->bounds[i]);
889             n += p->bounds[i];
890           }
891         }
892       } 
893       else if( p->num_edges > 0 ) {
894 #ifndef OGLBUG
895         if( p->edge_vis ) {
896           glBegin( draw_mode );
897           for( i=0 ; i<p->num_edges ; i++ ) {
898             glEdgeFlag( p->edge_vis[i] );
899             glVertex3fv( &p->vertices[p->edges[i]].xyz[0] );
900           }
901           glEnd();
902         } else
903 #endif
904       if( renderMode == GL_FEEDBACK )
905         draw_primitive_elements( p, draw_mode, p->num_edges, 
906                                   GL_UNSIGNED_INT,(GLenum*) p->edges);
907       else
908         glDrawElements( draw_mode, p->num_edges, 
909                                   GL_UNSIGNED_INT, p->edges);
910       } else {
911       if( renderMode == GL_FEEDBACK )
912         draw_primitive_array( p, draw_mode, 0, p->num_vertexs);
913       else
914         glDrawArrays( draw_mode, 0, p->num_vertexs);
915       }
916     }
917
918   if( draw_mode > GL_LINE_STRIP ) {
919     CMN_KEY k;
920     if( line_width_preserve != edge_width ) {
921       k.id = TelPolylineWidth;
922       k.data.fdata = line_width_preserve;
923       TsmSetAttri( 1, &k );
924     }
925     if( line_type_preserve != edge_type ) {
926       k.id = TelPolylineType;
927       k.data.ldata = line_type_preserve;
928       TsmSetAttri( 1, &k );
929     }
930     glPopAttrib();
931   }
932 }
933
934 /*----------------------------------------------------------------------*/
935 static void draw_degenerates_points_as_points ( call_def_parray p ) { 
936
937   Tint       j;
938   tel_point  pv = p -> vertices;
939
940 #ifdef FULL_DEGENER
941   if ( g_fSkipRatio == 1. )
942     return;
943 #endif
944
945   for ( j=0 ; j<p->num_vertexs ; j++ ) {
946     glVertex3fv ( &pv[j].xyz[0] );
947   }
948 }  
949
950 /*----------------------------------------------------------------------*/
951 static void draw_degenerates_lines_as_points ( call_def_parray p ) { 
952
953   Tint       j;
954   GLfloat    pt[ 3 ];
955   tel_point  pv = p -> vertices;
956
957 #ifdef FULL_DEGENER
958   if ( g_fSkipRatio == 1. )
959     return;
960 #endif
961
962   for ( j=0 ; j<p->num_vertexs ; j+=2 ) {
963     pt[0] = pt[1] = pt[2] = 0.;
964     pt[ 0 ] += pv[j].xyz[ 0 ];
965     pt[ 1 ] += pv[j].xyz[ 1 ];
966     pt[ 2 ] += pv[j].xyz[ 2 ];
967     pt[ 0 ] += pv[j+1].xyz[ 0 ];
968     pt[ 1 ] += pv[j+1].xyz[ 1 ];
969     pt[ 2 ] += pv[j+1].xyz[ 2 ];
970     pt[ 0 ] /= 2;
971     pt[ 1 ] /= 2;
972     pt[ 2 ] /= 2;
973     glVertex3fv ( pt );
974   }
975 }  
976
977 /*----------------------------------------------------------------------*/
978 static void draw_degenerates_triangles_as_points ( call_def_parray p ) { 
979
980   Tint       i, j, iv;
981   GLfloat    pt[ 3 ];
982   tel_point  pv = p -> vertices;
983
984 #ifdef FULL_DEGENER
985   if ( g_fSkipRatio == 1. )
986     return;
987 #endif
988
989   if( p->num_edges > 0 ) {
990     for ( j=0 ; j<p->num_edges ; j+=3 ) {
991       pt[0] = pt[1] = pt[2] = 0.;
992       for ( i=0 ; i<3 ; i++ ) {
993         iv = p->edges[j+i];
994         pt[ 0 ] += pv[iv].xyz[ 0 ];
995         pt[ 1 ] += pv[iv].xyz[ 1 ];
996         pt[ 2 ] += pv[iv].xyz[ 2 ];
997       }
998       pt[ 0 ] /= 3;
999       pt[ 1 ] /= 3;
1000       pt[ 2 ] /= 3;
1001       glVertex3fv ( pt );
1002     }
1003   } else {
1004     for ( j=0 ; j<p->num_vertexs ; j+=3 ) {
1005       pt[0] = pt[1] = pt[2] = 0.;
1006       for ( i=0 ; i<3 ; i++ ) {
1007         pt[ 0 ] += pv[j+i].xyz[ 0 ];
1008         pt[ 1 ] += pv[j+i].xyz[ 1 ];
1009         pt[ 2 ] += pv[j+i].xyz[ 2 ];
1010       }
1011       pt[ 0 ] /= 3;
1012       pt[ 1 ] /= 3;
1013       pt[ 2 ] /= 3;
1014       glVertex3fv ( pt );
1015     }
1016   }
1017 }  
1018
1019 /*----------------------------------------------------------------------*/
1020 static void draw_degenerates_trianglestrips_as_points ( call_def_parray p ) { 
1021
1022   Tint       i, j, k, n;
1023   GLfloat    pt[ 3 ];
1024   tel_point  pv = p -> vertices;
1025
1026 #ifdef FULL_DEGENER
1027   if ( g_fSkipRatio == 1. )
1028     return;
1029 #endif
1030
1031   if( p->num_bounds > 0 ) {
1032     for ( k=n=0 ; k<p->num_bounds ; k++ ) {
1033       for ( j=0 ; j<p->bounds[k]-2 ; j++ ) {
1034         pt[0] = pt[1] = pt[2] = 0.;
1035         for ( i=0 ; i<3 ; i++ ) {
1036           pt[ 0 ] += pv[n+j+i].xyz[ 0 ];
1037           pt[ 1 ] += pv[n+j+i].xyz[ 1 ];
1038           pt[ 2 ] += pv[n+j+i].xyz[ 2 ];
1039         }
1040         pt[ 0 ] /= 3;
1041         pt[ 1 ] /= 3;
1042         pt[ 2 ] /= 3;
1043         glVertex3fv ( pt );
1044       }
1045       n += p->bounds[k];
1046     }
1047   } else {
1048     for ( j=0 ; j<p->num_vertexs-2 ; j++ ) {
1049       pt[0] = pt[1] = pt[2] = 0.;
1050       for ( i=0 ; i<3 ; i++ ) {
1051         pt[ 0 ] += pv[j+i].xyz[ 0 ];
1052         pt[ 1 ] += pv[j+i].xyz[ 1 ];
1053         pt[ 2 ] += pv[j+i].xyz[ 2 ];
1054       }
1055       pt[ 0 ] /= 3;
1056       pt[ 1 ] /= 3;
1057       pt[ 2 ] /= 3;
1058       glVertex3fv ( pt );
1059     }
1060   }
1061 }  
1062
1063 /*----------------------------------------------------------------------*/
1064 static void draw_degenerates_polygons_as_points ( call_def_parray p ) { 
1065
1066   Tint       j, k, n, iv;
1067   GLfloat    pt[ 3 ];
1068   tel_point  pv = p -> vertices;
1069
1070 #ifdef FULL_DEGENER
1071   if ( g_fSkipRatio == 1. )
1072     return;
1073 #endif
1074
1075   if( p->num_bounds > 0 ) {
1076     if( p->num_edges > 0 ) {
1077       for ( k=n=0 ; k<p->num_bounds ; k++ ) {
1078         pt[0] = pt[1] = pt[2] = 0.;
1079         for ( j=0 ; j<p->bounds[k] ; j++ ) {
1080           iv = p->edges[n+j];
1081           pt[ 0 ] += pv[iv].xyz[ 0 ];
1082           pt[ 1 ] += pv[iv].xyz[ 1 ];
1083           pt[ 2 ] += pv[iv].xyz[ 2 ];
1084         }
1085         pt[ 0 ] /= p->bounds[k];
1086         pt[ 1 ] /= p->bounds[k];
1087         pt[ 2 ] /= p->bounds[k];
1088         glVertex3fv ( pt );
1089         n += p->bounds[k];
1090       }
1091     } else {  
1092       for ( k=n=0 ; k<p->num_bounds ; k++ ) {
1093         pt[0] = pt[1] = pt[2] = 0.;
1094         for ( j=0 ; j<p->bounds[k] ; j++ ) {
1095           pt[ 0 ] += pv[n+j].xyz[ 0 ];
1096           pt[ 1 ] += pv[n+j].xyz[ 1 ];
1097           pt[ 2 ] += pv[n+j].xyz[ 2 ];
1098         }
1099         pt[ 0 ] /= p->bounds[k];
1100         pt[ 1 ] /= p->bounds[k];
1101         pt[ 2 ] /= p->bounds[k];
1102         glVertex3fv ( pt );
1103         n += p->bounds[k];
1104       }
1105     }
1106   } else if( p->num_edges > 0 ) {
1107     pt[0] = pt[1] = pt[2] = 0.;
1108     for ( j=0 ; j<p->num_edges ; j++ ) {
1109       iv = p->edges[j];
1110       pt[ 0 ] += pv[iv].xyz[ 0 ];
1111       pt[ 1 ] += pv[iv].xyz[ 1 ];
1112       pt[ 2 ] += pv[iv].xyz[ 2 ];
1113     }
1114     pt[ 0 ] /= p->num_edges;
1115     pt[ 1 ] /= p->num_edges;
1116     pt[ 2 ] /= p->num_edges;
1117     glVertex3fv ( pt );
1118   } else {
1119     pt[0] = pt[1] = pt[2] = 0.;
1120     for ( j=0 ; j<p->num_vertexs ; j++ ) {
1121       pt[ 0 ] += pv[j].xyz[ 0 ];
1122       pt[ 1 ] += pv[j].xyz[ 1 ];
1123       pt[ 2 ] += pv[j].xyz[ 2 ];
1124     }
1125     pt[ 0 ] /= p->num_vertexs;
1126     pt[ 1 ] /= p->num_vertexs;
1127     pt[ 2 ] /= p->num_vertexs;
1128     glVertex3fv ( pt );
1129   }
1130 }  
1131
1132 /*----------------------------------------------------------------------*/
1133 static void draw_degenerates_quadrangles_as_points ( call_def_parray p ) { 
1134
1135   Tint       i, j, iv;
1136   GLfloat    pt[ 3 ];
1137   tel_point  pv = p -> vertices;
1138
1139 #ifdef FULL_DEGENER
1140   if ( g_fSkipRatio == 1. )
1141     return;
1142 #endif
1143
1144   if( p->num_edges > 0 ) {
1145     for ( j=0 ; j<p->num_edges ; j+=4 ) {
1146       pt[0] = pt[1] = pt[2] = 0.;
1147       for ( i=0 ; i<4 ; i++ ) {
1148         iv = p->edges[j+i];
1149         pt[ 0 ] += pv[iv].xyz[ 0 ];
1150         pt[ 1 ] += pv[iv].xyz[ 1 ];
1151         pt[ 2 ] += pv[iv].xyz[ 2 ];
1152       }
1153       pt[ 0 ] /= 4;
1154       pt[ 1 ] /= 4;
1155       pt[ 2 ] /= 4;
1156       glVertex3fv ( pt );
1157     }
1158   } else {
1159     for ( j=0 ; j<p->num_vertexs ; j+=4 ) {
1160       pt[0] = pt[1] = pt[2] = 0.;
1161       for ( i=0 ; i<4 ; i++ ) {
1162         pt[ 0 ] += pv[j+i].xyz[ 0 ];
1163         pt[ 1 ] += pv[j+i].xyz[ 1 ];
1164         pt[ 2 ] += pv[j+i].xyz[ 2 ];
1165       }
1166       pt[ 0 ] /= 4;
1167       pt[ 1 ] /= 4;
1168       pt[ 2 ] /= 4;
1169       glVertex3fv ( pt );
1170     }
1171   }
1172 }  
1173
1174 /*----------------------------------------------------------------------*/
1175 static void draw_degenerates_quadranglestrips_as_points ( call_def_parray p ) { 
1176
1177   Tint       i, j, k, n;
1178   GLfloat    pt[ 3 ];
1179   tel_point  pv = p -> vertices;
1180
1181 #ifdef FULL_DEGENER
1182   if ( g_fSkipRatio == 1. )
1183     return;
1184 #endif
1185
1186   if( p->num_bounds > 0 ) {
1187     for ( k=n=0 ; k<p->num_bounds ; k++ ) {
1188       for ( j=0 ; j<p->bounds[k]-2 ; j+=2 ) {
1189         pt[0] = pt[1] = pt[2] = 0.;
1190         for ( i=0 ; i<4 ; i++ ) {
1191           pt[ 0 ] += pv[n+j+i].xyz[ 0 ];
1192           pt[ 1 ] += pv[n+j+i].xyz[ 1 ];
1193           pt[ 2 ] += pv[n+j+i].xyz[ 2 ];
1194         }
1195         pt[ 0 ] /= 4;
1196         pt[ 1 ] /= 4;
1197         pt[ 2 ] /= 4;
1198         glVertex3fv ( pt );
1199       }
1200       n += p->bounds[k];
1201     }
1202   } else {
1203     for ( j=0 ; j<p->num_vertexs-2 ; j+=2 ) {
1204       pt[0] = pt[1] = pt[2] = 0.;
1205       for ( i=0 ; i<4 ; i++ ) {
1206         pt[ 0 ] += pv[j+i].xyz[ 0 ];
1207         pt[ 1 ] += pv[j+i].xyz[ 1 ];
1208         pt[ 2 ] += pv[j+i].xyz[ 2 ];
1209       }
1210       pt[ 0 ] /= 4;
1211       pt[ 1 ] /= 4;
1212       pt[ 2 ] /= 4;
1213       glVertex3fv ( pt );
1214     }
1215   }
1216 }  
1217
1218 /*----------------------------------------------------------------------*/
1219 static void draw_degenerates_as_points ( call_def_parray p, 
1220                                         tel_colour edge_colour ) 
1221 {
1222
1223   GLboolean zbuff_state = glIsEnabled(GL_DEPTH_TEST);
1224   LightOff ();
1225   if( zbuff_state ) glDisable(GL_DEPTH_TEST); 
1226   glColor3fv( edge_colour->rgb );
1227   glBegin ( GL_POINTS );
1228   switch( draw_mode ) {
1229       case GL_POINTS:
1230         draw_degenerates_points_as_points( p );
1231         break;
1232       case GL_LINES:
1233         draw_degenerates_lines_as_points( p );
1234         break;
1235       case GL_LINE_STRIP:
1236       case GL_POLYGON:
1237         draw_degenerates_polygons_as_points( p );
1238         break;
1239       case GL_TRIANGLES:
1240         draw_degenerates_triangles_as_points( p );
1241         break;
1242       case GL_QUADS:
1243         draw_degenerates_quadrangles_as_points( p );
1244         break;
1245       case GL_TRIANGLE_FAN:
1246       case GL_TRIANGLE_STRIP:
1247         draw_degenerates_trianglestrips_as_points( p );
1248         break;
1249       case GL_QUAD_STRIP:
1250         draw_degenerates_quadranglestrips_as_points( p );
1251         break;
1252       default:
1253         break;
1254   }
1255
1256   glEnd ();
1257
1258   if( zbuff_state ) glEnable(GL_DEPTH_TEST); 
1259 }
1260
1261 /*----------------------------------------------------------------------*/
1262 static void draw_degenerates_lines_as_lines ( call_def_parray p ) { 
1263
1264   Tint       i,j,n,iv;
1265   tel_point  pv = p -> vertices;
1266
1267   n = p->num_vertexs;
1268   j = (int)((1.-g_fSkipRatio)*n);
1269   while ( j-- ) {
1270     i = OGL_Rand() % n;
1271     p->keys[i] = -p->keys[i];
1272   };
1273
1274   if( p->num_bounds > 0 ) {
1275     if( p->num_edges > 0 ) {
1276       for ( i=n=0 ; i<p->num_bounds ; i++ ) {
1277         glBegin ( GL_LINES );
1278         for ( j=0 ; j<p->bounds[i] ; j++ ) {
1279           iv = p->edges[n+j];
1280           if( p->keys[iv] < 0 ) {
1281             p->keys[iv] = -p->keys[iv];
1282             glVertex3fv ( pv[iv].xyz );
1283           }
1284         }
1285         glEnd();
1286         n += p->bounds[i];
1287       }
1288     } else {  
1289       for ( i=n=0 ; i<p->num_bounds ; i++ ) {
1290         glBegin ( GL_LINES );
1291         for ( j=0 ; j<p->bounds[i] ; j++ ) {
1292           if( p->keys[n+j] < 0 ) {
1293             p->keys[n+j] = -p->keys[n+j];
1294             glVertex3fv ( pv[n+j].xyz );
1295           }
1296         }
1297         glEnd();
1298         n += p->bounds[i];
1299       }
1300     }
1301   } else if( p->num_edges > 0 ) {
1302     glBegin ( GL_LINES );
1303     for ( j=0 ; j<p->num_edges ; j++ ) {
1304       iv = p->edges[j];
1305       if( p->keys[iv] < 0 ) {
1306         p->keys[iv] = -p->keys[iv];
1307         glVertex3fv ( pv[iv].xyz );
1308       }
1309     }
1310     glEnd();
1311   } else {
1312     glBegin ( GL_LINES );
1313     for ( j=0 ; j<p->num_vertexs ; j++ ) {
1314       if( p->keys[j] < 0 ) {
1315         p->keys[j] = -p->keys[j];
1316         glVertex3fv ( pv[j].xyz );
1317       }
1318     }
1319     glEnd();
1320   }
1321 }  
1322
1323 /*----------------------------------------------------------------------*/
1324 static void draw_degenerates_triangles_as_lines ( call_def_parray p ) 
1325
1326
1327   Tint       i,j,n,iv;
1328   tel_point  pv = p -> vertices;
1329
1330   n = p->num_vertexs/3;
1331   j = (int)((1.-g_fSkipRatio)*n);
1332   while ( j-- ) {
1333     i = OGL_Rand() % n; i *= 3;
1334     p->keys[i] = -p->keys[i];
1335   };
1336
1337   if( p->num_edges > 0 ) {
1338     for ( j=0 ; j<p->num_edges ; j+=3 ) {
1339       iv = p->edges[j];
1340       if( p->keys[iv] < 0 ) { 
1341         p->keys[iv] = -p->keys[iv];
1342         glBegin ( GL_LINE_LOOP );
1343         for ( i=0 ; i<3 ; i++ ) {
1344           iv = p->edges[j+i];
1345           glVertex3fv ( pv[iv].xyz );
1346         }
1347         glEnd();
1348       }
1349     }
1350   } else {
1351     for ( j=0 ; j<p->num_vertexs ; j+=3 ) {
1352       if( p->keys[j] < 0 ) { 
1353         p->keys[j] = -p->keys[j];
1354         glBegin ( GL_LINE_LOOP );
1355         for ( i=0 ; i<3 ; i++ ) {
1356           glVertex3fv ( pv[j+i].xyz );
1357         }
1358         glEnd();
1359       }
1360     }
1361   }
1362 }  
1363
1364 /*----------------------------------------------------------------------*/
1365 static void draw_degenerates_trianglestrips_as_lines ( call_def_parray p ) 
1366
1367
1368   Tint       i,j,k,n,ni;
1369   tel_point  pv = p -> vertices;
1370
1371   if( p->num_bounds > 0 ) {
1372     for ( i=n=0 ; i<p->num_bounds ; i++ ) {
1373       ni = p->bounds[i]-2;
1374       k = (int)((1.-g_fSkipRatio)*ni);
1375       while ( k-- ) {
1376         j = OGL_Rand() % ni; j += 2;
1377         p->keys[n+j] = -p->keys[n+j];
1378       };
1379       for ( j=2 ; j<p->bounds[i] ; j++ ) {
1380         if( p->keys[n+j] < 0 ) { 
1381           p->keys[n+j] = -p->keys[n+j];
1382           glBegin ( GL_LINE_LOOP );
1383           glVertex3fv ( pv[n+j-2].xyz );
1384           glVertex3fv ( pv[n+j-1].xyz );
1385           glVertex3fv ( pv[n+j].xyz );
1386           glEnd();
1387         }
1388       }
1389       n += p->bounds[i];
1390     }
1391   } else {
1392     ni = p->num_vertexs-2;
1393     k = (int)((1.-g_fSkipRatio)*ni);
1394     while ( k-- ) {
1395       j = OGL_Rand() % ni; j += 2;
1396       p->keys[j] = -p->keys[j];
1397     };
1398     for ( j=2 ; j<p->num_vertexs ; j++ ) {
1399       if( p->keys[j] < 0 ) { 
1400         p->keys[j] = -p->keys[j];
1401         glBegin ( GL_LINE_LOOP );
1402         glVertex3fv ( pv[j-2].xyz );
1403         glVertex3fv ( pv[j-1].xyz );
1404         glVertex3fv ( pv[j].xyz );
1405         glEnd();
1406       }
1407     }
1408   }
1409 }  
1410
1411 /*----------------------------------------------------------------------*/
1412 static void draw_degenerates_polygons_as_lines ( call_def_parray p )
1413
1414   Tint       i,j,n,iv;
1415   tel_point  pv = p -> vertices;
1416
1417   n = p->num_vertexs;
1418   j = (int)((1.-g_fSkipRatio)*n);
1419   while ( j-- ) {
1420     i = OGL_Rand() % n;
1421     p->keys[i] = -p->keys[i];
1422   };
1423
1424   if( p->num_bounds > 0 ) {
1425     if( p->num_edges > 0 ) {
1426       for ( i=n=0 ; i<p->num_bounds ; i++ ) {
1427         glBegin ( GL_LINE_LOOP );
1428         for ( j=0 ; j<p->bounds[i] ; j++ ) {
1429           iv = p->edges[n+j];
1430           if( p->keys[iv] < 0 ) {
1431             p->keys[iv] = -p->keys[iv];
1432             glVertex3fv ( pv[iv].xyz );
1433           }
1434         }
1435         glEnd();
1436         n += p->bounds[i];
1437       }
1438     } else {  
1439       for ( i=n=0 ; i<p->num_bounds ; i++ ) {
1440         glBegin ( GL_LINE_LOOP );
1441         for ( j=0 ; j<p->bounds[i] ; j++ ) {
1442           if( p->keys[n+j] < 0 ) {
1443             p->keys[n+j] = -p->keys[n+j];
1444             glVertex3fv ( pv[n+j].xyz );
1445           }
1446         }
1447         glEnd();
1448         n += p->bounds[i];
1449       }
1450     }
1451   } else if( p->num_edges > 0 ) {
1452     glBegin ( GL_LINE_LOOP );
1453     for ( j=0 ; j<p->num_edges ; j++ ) {
1454       iv = p->edges[j];
1455       if( p->keys[iv] < 0 ) {
1456         p->keys[iv] = -p->keys[iv];
1457         glVertex3fv ( pv[iv].xyz );
1458       }
1459     }
1460     glEnd();
1461   } else {
1462     glBegin ( GL_LINE_LOOP );
1463     for ( j=0 ; j<p->num_vertexs ; j++ ) {
1464       if( p->keys[j] < 0 ) {
1465         p->keys[j] = -p->keys[j];
1466         glVertex3fv ( pv[j].xyz );
1467       }
1468     }
1469     glEnd();
1470   }
1471
1472 }  
1473
1474 /*----------------------------------------------------------------------*/
1475 static void draw_degenerates_quadrangles_as_lines ( call_def_parray p ) 
1476
1477
1478   Tint       i,j,n,iv;
1479   tel_point  pv = p -> vertices;
1480
1481   n = p->num_vertexs/4;
1482   j = (int)((1.-g_fSkipRatio)*n);
1483   while ( j-- ) {
1484     i = OGL_Rand() % n; i *= 4;
1485     p->keys[i] = -p->keys[i];
1486   };
1487
1488   if( p->num_edges > 0 ) {
1489     for ( j=0 ; j<p->num_edges ; j+=4 ) {
1490       iv = p->edges[j];
1491       if( p->keys[iv] < 0 ) {
1492         p->keys[iv] = -p->keys[iv];
1493         glBegin ( GL_LINE_LOOP );
1494         for ( i=0 ; i<4 ; i++ ) {
1495           iv = p->edges[j+i];
1496           glVertex3fv ( pv[iv].xyz );
1497         }
1498         glEnd();
1499       }
1500     }
1501   } else {
1502     for ( j=0 ; j<p->num_vertexs ; j+=4 ) {
1503       if( p->keys[j] < 0 ) {
1504         p->keys[j] = -p->keys[j];
1505         glBegin ( GL_LINE_LOOP );
1506         for ( i=0 ; i<4 ; i++ ) {
1507           glVertex3fv ( pv[j+i].xyz );
1508         }
1509         glEnd();
1510       }
1511     }
1512   }
1513 }  
1514
1515 /*----------------------------------------------------------------------*/
1516 static void draw_degenerates_quadranglestrips_as_lines ( call_def_parray p )
1517
1518
1519   Tint       i,j,k,n,ni;
1520   tel_point  pv = p -> vertices;
1521
1522   if( p->num_bounds > 0 ) {
1523     for ( i=n=0 ; i<p->num_bounds ; i++ ) {
1524       ni = p->bounds[i]/2-2;
1525       k = (int)((1.-g_fSkipRatio)*ni);
1526       while ( k-- ) {
1527         j = OGL_Rand() % ni; j = j*2+2;
1528         p->keys[n+j] = -p->keys[n+j];
1529       };
1530       for ( j=3 ; j<p->bounds[i] ; j+=2 ) {
1531         if( p->keys[n+j] < 0 ) {
1532           p->keys[n+j] = -p->keys[n+j];
1533           glBegin ( GL_LINE_LOOP );
1534           glVertex3fv ( pv[n+j-3].xyz );
1535           glVertex3fv ( pv[n+j-2].xyz );
1536           glVertex3fv ( pv[n+j-1].xyz );
1537           glVertex3fv ( pv[n+j].xyz );
1538           glEnd();
1539         }
1540       }
1541       n += p->bounds[i];
1542     }
1543   } else {
1544     ni = p->num_vertexs/2-2;
1545     k = (int)((1.-g_fSkipRatio)*ni);
1546     while ( k-- ) {
1547       j = OGL_Rand() % ni; j = j*2+2;
1548       p->keys[j] = -p->keys[j];
1549     };
1550     for ( j=3 ; j<p->num_vertexs ; j+=2 ) {
1551       if( p->keys[j] < 0 ) {
1552         p->keys[j] = -p->keys[j];
1553         glBegin ( GL_LINE_LOOP );
1554         glVertex3fv ( pv[j-3].xyz );
1555         glVertex3fv ( pv[j-2].xyz );
1556         glVertex3fv ( pv[j-1].xyz );
1557         glVertex3fv ( pv[j].xyz );
1558         glEnd();
1559       }
1560     }
1561   }
1562 }  
1563
1564 /*----------------------------------------------------------------------*/
1565 static void draw_degenerates_as_lines ( call_def_parray p, 
1566                                        tel_colour edge_colour )
1567 {
1568
1569   GLint renderMode;
1570
1571   GLboolean zbuff_state = glIsEnabled(GL_DEPTH_TEST);
1572
1573   LightOff ();
1574
1575   if( zbuff_state ) glDisable(GL_DEPTH_TEST); 
1576
1577   glColor3fv( edge_colour->rgb );
1578
1579   if( g_fSkipRatio != 0 ) switch( draw_mode ) {
1580       case GL_POINTS:
1581         draw_degenerates_points_as_points( p );
1582         break;
1583       case GL_LINES:
1584         draw_degenerates_lines_as_lines( p );
1585         break;
1586       case GL_LINE_STRIP:
1587       case GL_POLYGON:
1588         draw_degenerates_polygons_as_lines( p );
1589         break;
1590       case GL_TRIANGLES:
1591         draw_degenerates_triangles_as_lines( p );
1592         break;
1593       case GL_QUADS:
1594         draw_degenerates_quadrangles_as_lines( p );
1595         break;
1596       case GL_TRIANGLE_FAN:
1597       case GL_TRIANGLE_STRIP:
1598         draw_degenerates_trianglestrips_as_lines( p );
1599         break;
1600       case GL_QUAD_STRIP:
1601         draw_degenerates_quadranglestrips_as_lines( p );
1602         break;
1603       default:
1604         break;
1605   }
1606   else {
1607     int i,n;
1608
1609 #ifdef OCC3192
1610     GLboolean color_array_mode, 
1611       edge_flag_array_mode,
1612       index_array_mode,
1613       normal_array_mode,
1614       texture_coord_array_mode,
1615       vertex_array_mode;
1616 #endif
1617     glPushAttrib( GL_POLYGON_BIT );
1618     glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
1619
1620 #ifdef OCC3192
1621     color_array_mode         = glIsEnabled( GL_COLOR_ARRAY );
1622     edge_flag_array_mode     = glIsEnabled( GL_EDGE_FLAG_ARRAY );
1623     index_array_mode         = glIsEnabled( GL_INDEX_ARRAY );
1624     normal_array_mode        = glIsEnabled( GL_NORMAL_ARRAY );
1625     texture_coord_array_mode = glIsEnabled( GL_TEXTURE_COORD_ARRAY );
1626     vertex_array_mode        = glIsEnabled( GL_VERTEX_ARRAY );
1627
1628     glDisableClientState( GL_COLOR_ARRAY );
1629     glDisableClientState( GL_EDGE_FLAG_ARRAY );
1630     glDisableClientState( GL_INDEX_ARRAY );
1631     glDisableClientState( GL_NORMAL_ARRAY );
1632     glDisableClientState( GL_TEXTURE_COORD_ARRAY );
1633
1634     if( !vertex_array_mode ) glEnableClientState( GL_VERTEX_ARRAY );
1635 #else
1636     glEnableClientState( GL_VERTEX_ARRAY );
1637 #endif
1638     glVertexPointer(3, GL_FLOAT, 0, p->vertices); /* array of vertices  */
1639
1640     glGetIntegerv( GL_RENDER_MODE, &renderMode );
1641
1642     if( p->num_bounds > 0 ) {
1643       if( p->num_edges > 0 ) {
1644         for( i=n=0 ; i<p->num_bounds ; i++ ) {
1645           if( renderMode == GL_FEEDBACK )
1646             draw_primitive_elements( p, draw_mode, p->bounds[i], 
1647             GL_UNSIGNED_INT, (GLenum*) &p->edges[n]);
1648           else
1649             glDrawElements( draw_mode, p->bounds[i],
1650             GL_UNSIGNED_INT, &p->edges[n]);
1651           n += p->bounds[i];
1652         }
1653       } else {
1654         for( i=n=0 ; i<p->num_bounds ; i++ ) {
1655           if( renderMode == GL_FEEDBACK )
1656             draw_primitive_array( p, draw_mode, n, p->bounds[i]);
1657           else
1658             glDrawArrays( draw_mode, n, p->bounds[i]);
1659           n += p->bounds[i];
1660         }
1661       }
1662     } else if( p->num_edges > 0 ) {
1663       if( renderMode == GL_FEEDBACK )
1664         draw_primitive_elements( p, draw_mode, p->num_edges, 
1665         GL_UNSIGNED_INT, (GLenum*) p->edges);
1666       else
1667         glDrawElements( draw_mode, p->num_edges,
1668         GL_UNSIGNED_INT, p->edges);
1669     } else {
1670       if( renderMode == GL_FEEDBACK )
1671         draw_primitive_array( p, draw_mode, 0, p->num_vertexs);
1672       else
1673         glDrawArrays( draw_mode, 0, p->num_vertexs);
1674     }
1675
1676 #ifdef OCC3192
1677     if( !vertex_array_mode ) glDisableClientState( GL_VERTEX_ARRAY );
1678
1679     if( color_array_mode )         glEnableClientState( GL_COLOR_ARRAY );
1680     if( edge_flag_array_mode )     glEnableClientState( GL_EDGE_FLAG_ARRAY );
1681     if( index_array_mode )         glEnableClientState( GL_INDEX_ARRAY );
1682     if( normal_array_mode )        glEnableClientState( GL_NORMAL_ARRAY );
1683     if( texture_coord_array_mode ) glEnableClientState( GL_TEXTURE_COORD_ARRAY );
1684 #endif
1685     glPopAttrib();
1686   }
1687
1688   if( zbuff_state ) glEnable(GL_DEPTH_TEST); 
1689
1690 }  
1691
1692 static void draw_degenerates_as_bboxs ( call_def_parray p, 
1693                                         tel_colour edge_colour )
1694 {
1695
1696   Tint      i;
1697   GLfloat   minp[ 3 ] = { FLT_MAX, FLT_MAX, FLT_MAX };
1698   GLfloat   maxp[ 3 ] = { FLT_MIN, FLT_MIN, FLT_MIN };
1699   tel_point pv = p -> vertices;
1700
1701   LightOff ();
1702
1703   glColor3fv( edge_colour->rgb );
1704
1705   for ( i=0 ; i<p->num_vertexs ; ++i ) {
1706     if ( pv[  i  ].xyz[ 0 ] < minp[ 0 ] )
1707       minp[ 0 ] = pv[  i  ].xyz[ 0 ] ;
1708     if ( pv[  i  ].xyz[ 1 ] < minp[ 1 ] )
1709       minp[ 1 ] = pv[  i  ].xyz[ 1 ] ;
1710     if ( pv[  i  ].xyz[ 2 ] < minp[ 2 ] )
1711       minp[ 2 ] = pv[  i  ].xyz[ 2 ] ;
1712
1713     if ( pv[  i  ].xyz[ 0 ] > maxp[ 0 ] )
1714       maxp[ 0 ] = pv[  i  ].xyz[ 0 ] ;
1715     if ( pv[  i  ].xyz[ 1 ] > maxp[ 1 ] )
1716       maxp[ 1 ] = pv[  i  ].xyz[ 1 ] ;
1717     if ( pv[  i ].xyz[ 2 ] > maxp[ 2 ] )
1718       maxp[ 2 ] = pv[  i  ].xyz[ 2 ] ;
1719   }  /* end for ( i ) */
1720
1721   glBegin ( GL_LINE_STRIP );
1722
1723   glVertex3fv ( minp );
1724   glVertex3f ( minp[ 0 ], maxp[ 1 ], minp[ 2 ] );
1725   glVertex3f ( minp[ 0 ], maxp[ 1 ], maxp[ 2 ] );
1726   glVertex3f ( minp[ 0 ], minp[ 1 ], maxp[ 2 ] );
1727   glVertex3f ( minp[ 0 ], minp[ 1 ], minp[ 2 ] );
1728
1729   glVertex3f ( maxp[ 0 ], minp[ 1 ], minp[ 2 ] );
1730   glVertex3f ( maxp[ 0 ], maxp[ 1 ], minp[ 2 ] );
1731   glVertex3f ( maxp[ 0 ], maxp[ 1 ], maxp[ 2 ] );
1732   glVertex3f ( maxp[ 0 ], minp[ 1 ], maxp[ 2 ] );
1733   glVertex3f ( maxp[ 0 ], minp[ 1 ], minp[ 2 ] );
1734
1735   glVertex3f ( maxp[ 0 ], minp[ 1 ], maxp[ 2 ] );
1736   glVertex3f ( minp[ 0 ], minp[ 1 ], maxp[ 2 ] );
1737   glVertex3f ( minp[ 0 ], maxp[ 1 ], maxp[ 2 ] );
1738   glVertex3fv ( maxp );
1739   glVertex3f ( maxp[ 0 ], maxp[ 1 ], minp[ 2 ] );
1740   glVertex3f ( minp[ 0 ], maxp[ 1 ], minp[ 2 ] );
1741
1742   glEnd();
1743
1744 }  /* end draw_degenerates_as_bboxs */