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