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