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