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