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