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