0022819: Redesign of OpenGl driver
[occt.git] / src / OpenGl / OpenGl_QuadrangleStrip.cxx
1 // File:      OpenGl_QuadrangleStrip.cxx
2 // Created:   13 July 2011
3 // Author:    Sergey ZERCHANINOV
4 // Copyright: OPEN CASCADE 2011
5
6 #include <OpenGl_tgl_all.hxx>
7 #include <GL/gl.h>
8
9 #include <OpenGl_QuadrangleStrip.hxx>
10
11 #include <OpenGl_telem_util.hxx>
12 #include <OpenGl_TextureBox.hxx>
13
14 #include <OpenGl_AspectFace.hxx>
15 #include <OpenGl_Structure.hxx>
16
17 /*----------------------------------------------------------------------*/
18
19 #define OPENGL_RAND() ( ( unsigned )( s_Rand = s_Rand * 214013L + 2531011L ) )
20
21 /*----------------------------------------------------------------------*/
22
23 extern void draw_degenerates_as_points ( PDS_INTERNAL, tel_point, Tint, const Handle(OpenGl_Workspace) & );
24 extern void draw_degenerates_as_bboxs  ( PDS_INTERNAL, tel_point, Tint, const Handle(OpenGl_Workspace) & );
25 extern void set_drawable_items         ( GLboolean*, int, const float            );
26
27 /*----------------------------------------------------------------------*/
28
29 void OpenGl_QuadrangleStrip::draw_qstrip (const Tint front_lighting_model,
30                                          const Aspect_InteriorStyle interior_style,
31                                          const TEL_COLOUR *edge_colour,
32                                          const Handle(OpenGl_Workspace) &AWorkspace) const
33 {
34   Tint              i, m, newList = 0;
35   Tint              nf, nv, nr, nc;
36   Tint              lighting_model;
37
38   tel_point pfn = myData.fnormals;
39   tel_colour pfc = myData.fcolours;
40   tel_point pv  = myData.vertices;
41   tel_colour pvc = myData.vcolours;
42   tel_point pvn = myData.vnormals;
43   tel_texture_coord pvt = myData.vtexturecoord;
44
45   if ( AWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT )
46   {
47     pvc = 0;
48     pfc = 0;
49   }
50
51   if ( AWorkspace->DegenerateModel < 2 && interior_style != Aspect_IS_EMPTY )
52   {
53     if ( front_lighting_model )
54       glEnable(GL_LIGHTING);
55     else
56       glDisable(GL_LIGHTING);
57
58     lighting_model = front_lighting_model;
59     nr             = myData.num_rows;
60     nc             = myData.num_columns;
61     nf             = nr * nc;
62     nv             = ( nr + 1 ) * ( nc + 1 );
63     if ( (AWorkspace->NamedStatus & OPENGL_NS_ANIMATION) == 0 )
64       goto doDraw; /* Disable object display list out of animation */
65     /*  window's context and bitmap's one   */
66     if ( myDS->model != front_lighting_model || !myDS->list || myDS->model == -1 ||
67         ( AWorkspace->DegenerateModel && myDS->skipRatio != AWorkspace->SkipRatio ) )
68     {
69         myDS->skipRatio = AWorkspace->SkipRatio;
70         myDS->model     = front_lighting_model;
71         myDS->degMode   = AWorkspace->DegenerateModel;
72
73         if ( AWorkspace->SkipRatio == 0.f ) {
74
75           if ( !myDS->list ) myDS->list = glGenLists ( 1 );
76
77           glNewList ( myDS->list, GL_COMPILE_AND_EXECUTE );
78           newList = 1;
79 doDraw:
80           if ( lighting_model )
81           {
82             if ( pvt && (AWorkspace->NamedStatus & OPENGL_NS_FORBIDSETTEX) == 0 )
83             {
84               for ( m = 0; m < nr; ++m )
85               {
86                 glBegin ( GL_QUAD_STRIP );
87                 glNormal3fv   ( pvn[         m * ( nc + 1 ) ].xyz );
88                 glTexCoord2fv ( pvt[         m * ( nc + 1 ) ].xy  );
89                 glVertex3fv   ( pv[          m * ( nc + 1 ) ].xyz );
90                 glNormal3fv   ( pvn[ ( m + 1 ) * ( nc + 1 ) ].xyz );
91                 glTexCoord2fv ( pvt[ ( m + 1 ) * ( nc + 1 ) ].xy  );
92                 glVertex3fv   ( pv[  ( m + 1 ) * ( nc + 1 ) ].xyz );
93                 for ( i = 1; i < nc + 1; ++i )
94                 {
95                   glNormal3fv   ( pvn[         i + m * ( nc + 1 ) ].xyz );
96                   glTexCoord2fv ( pvt[         i + m * ( nc + 1 ) ].xy  );
97                   glVertex3fv   ( pv[          i + m * ( nc + 1 ) ].xyz );
98                   glNormal3fv   ( pvn[ i + ( m + 1 ) * ( nc + 1 ) ].xyz );
99                   glTexCoord2fv ( pvt[ i + ( m + 1 ) * ( nc + 1 ) ].xy  );
100                   glVertex3fv   ( pv[  i + ( m + 1 ) * ( nc + 1 ) ].xyz );
101                 }
102                 glEnd ();
103               }
104             }
105             else
106             {
107               for ( m = 0; m < nr; ++m )
108               {
109                 glBegin ( GL_QUAD_STRIP );
110                 glNormal3fv ( pvn[         m * ( nc + 1 ) ].xyz );
111                 glVertex3fv ( pv[          m * ( nc + 1 ) ].xyz );
112                 glNormal3fv ( pvn[ ( m + 1 ) * ( nc + 1 ) ].xyz );
113                 glVertex3fv ( pv[  ( m + 1 ) * ( nc + 1 ) ].xyz );
114                 for ( i = 1; i < nc + 1; ++i )
115                 {
116                   glNormal3fv ( pvn[         i + m * ( nc + 1 ) ].xyz );
117                   glVertex3fv ( pv[          i + m * ( nc + 1 ) ].xyz );
118                   glNormal3fv ( pvn[ i + ( m + 1 ) * ( nc + 1 ) ].xyz );
119                   glVertex3fv ( pv[  i + ( m + 1 ) * ( nc + 1 ) ].xyz );
120                 }
121                 glEnd ();
122               }
123             }
124           }
125           else
126           {
127             if ( pvc )
128             {
129               for ( m = 0; m < nr; ++m )
130               {
131                 glBegin ( GL_QUAD_STRIP );
132                 glColor3fv  ( pvc[         m * ( nc + 1 ) ].rgb );
133                 glVertex3fv ( pv[          m * ( nc + 1 ) ].xyz );
134                 glColor3fv  ( pvc[ ( m + 1 ) * ( nc + 1 ) ].rgb );
135                 glVertex3fv ( pv[  ( m + 1 ) * ( nc + 1 ) ].xyz );
136                 for ( i = 1; i < nc + 1; ++i )
137                 {
138                   glColor3fv  ( pvc[         i + m * ( nc + 1 ) ].rgb );
139                   glVertex3fv ( pv[          i + m * ( nc + 1 ) ].xyz );
140                   glColor3fv  ( pvc[ i + ( m + 1 ) * ( nc + 1 ) ].rgb );
141                   glVertex3fv ( pv[  i + ( m + 1 ) * ( nc + 1 ) ].xyz );
142                 }
143                 glEnd ();
144               }
145             }
146             else if ( pfc )
147             {
148               glColor3fv ( pfc[ 0 ].rgb );
149               for ( m = 0; m < nr; ++m )
150               {
151                 glBegin ( GL_QUAD_STRIP );
152                 glColor3fv  ( pfc[                m * nc ].rgb );
153                 glVertex3fv ( pv[         m * ( nc + 1 ) ].xyz );
154                 glVertex3fv ( pv[ ( m + 1 ) * ( nc + 1 ) ].xyz );
155                 for ( i = 1; i < nc + 1; ++i )
156                 {
157                   glVertex3fv ( pv[         i + m * ( nc + 1 ) ].xyz );
158                   glColor3fv  ( pfc[            i - 1 + m * nc ].rgb );
159                   glVertex3fv ( pv[ i + ( m + 1 ) * ( nc + 1 ) ].xyz );
160                 }
161                 glEnd ();
162               }
163             }
164             else
165             {
166               for ( m = 0; m < nr; ++m )
167               {
168                 glBegin ( GL_QUAD_STRIP );
169                 glVertex3fv ( pv[         m * ( nc + 1 ) ].xyz );
170                 glVertex3fv ( pv[ ( m + 1 ) * ( nc + 1 ) ].xyz );
171                 for ( i = 1; i < nc + 1; ++i )
172                 {
173                   glVertex3fv( pv[         i + m * ( nc + 1 ) ].xyz );
174                   glVertex3fv( pv[ i + ( m + 1 ) * ( nc + 1 ) ].xyz );
175                 }
176                 glEnd ();
177               }
178             }
179           }
180         }
181         else if ( AWorkspace->SkipRatio < 1.f )
182         {
183           set_drawable_items ( myDS->bDraw, nr, AWorkspace->SkipRatio );
184
185           if ( !myDS->dlist ) myDS->dlist = glGenLists ( 1 );
186
187           glNewList ( myDS->dlist, GL_COMPILE_AND_EXECUTE );
188           newList = 1;
189
190           if ( lighting_model )
191           {
192             if ( pvt && (AWorkspace->NamedStatus & OPENGL_NS_FORBIDSETTEX) == 0 )
193             {
194               for ( m = 0; m < nr; ++m )
195               {
196                 if ( myDS->bDraw[ m ] )
197                 {
198                   glBegin ( GL_QUADS );
199                   glNormal3fv   ( pvn[         m * ( nc + 1 ) ].xyz );
200                   glTexCoord2fv ( pvt[         m * ( nc + 1 ) ].xy  );
201                   glVertex3fv   ( pv[          m * ( nc + 1 ) ].xyz );
202                   glNormal3fv   ( pvn[ ( m + 1 ) * ( nc + 1 ) ].xyz );
203                   glTexCoord2fv ( pvt[ ( m + 1 ) * ( nc + 1 ) ].xy  );
204                   glVertex3fv   ( pv[  ( m + 1 ) * ( nc + 1 ) ].xyz );
205                   for ( i = 1; i < nc + 1; ++i )
206                   {
207                     glNormal3fv   ( pvn[ i + ( m + 1 ) * ( nc + 1 ) ].xyz );
208                     glTexCoord2fv ( pvt[ i + ( m + 1 ) * ( nc + 1 ) ].xy  );
209                     glVertex3fv   ( pv[  i + ( m + 1 ) * ( nc + 1 ) ].xyz );
210                     glNormal3fv   ( pvn[         i + m * ( nc + 1 ) ].xyz );
211                     glTexCoord2fv ( pvt[         i + m * ( nc + 1 ) ].xy  );
212                     glVertex3fv   ( pv[          i + m * ( nc + 1 ) ].xyz );
213                   }
214                   glEnd ();
215                 }
216               }
217             }
218             else
219             {
220               for ( m = 0; m < nr; ++m )
221                           {
222                 if ( myDS->bDraw[ m ] )
223                 {
224                   glBegin ( GL_QUADS );
225                   glNormal3fv ( pvn[         m * ( nc + 1 ) ].xyz );
226                   glVertex3fv ( pv[          m * ( nc + 1 ) ].xyz );
227                   glNormal3fv ( pvn[ ( m + 1 ) * ( nc + 1 ) ].xyz );
228                   glVertex3fv ( pv[  ( m + 1 ) * ( nc + 1 ) ].xyz );
229                   for ( i = 1; i < nc + 1; ++i )
230                   {
231                     glNormal3fv ( pvn[ i + ( m + 1 ) * ( nc + 1 ) ].xyz );
232                     glVertex3fv ( pv[  i + ( m + 1 ) * ( nc + 1 ) ].xyz );
233                     glNormal3fv ( pvn[         i + m * ( nc + 1 ) ].xyz );
234                     glVertex3fv ( pv[          i + m * ( nc + 1 ) ].xyz );
235                   }
236                   glEnd ();
237                 }
238               }
239             }
240           }
241           else
242           {
243             if ( pvc )
244             {
245               for ( m = 0; m < nr; ++m )
246               {
247                 if ( myDS->bDraw[ m ] )
248                 {
249                   glBegin ( GL_QUAD_STRIP );
250                   glColor3fv  ( pvc[         m * ( nc + 1 ) ].rgb );
251                   glVertex3fv ( pv[          m * ( nc + 1 ) ].xyz );
252                   glColor3fv  ( pvc[ ( m + 1 ) * ( nc + 1 ) ].rgb );
253                   glVertex3fv ( pv[  ( m + 1 ) * ( nc + 1 ) ].xyz );
254                   for ( i = 1; i < nc + 1; ++i )
255                   {
256                     glColor3fv  ( pvc[ i + ( m + 1 ) * ( nc + 1 ) ].rgb );
257                     glVertex3fv ( pv[  i + ( m + 1 ) * ( nc + 1 ) ].xyz );
258                     glColor3fv  ( pvc[         i + m * ( nc + 1 ) ].rgb );
259                     glVertex3fv ( pv[          i + m * ( nc + 1 ) ].xyz );
260                   }
261                   glEnd ();
262                 }
263               }
264             }
265             else if ( pfc )
266             {
267               glColor3fv ( pfc[ 0 ].rgb );
268               for ( m = 0; m < nr; ++m )
269               {
270                 if ( myDS->bDraw[ m ] )
271                 {
272                   glBegin ( GL_QUADS );
273                   glColor3fv  ( pfc[                m * nc ].rgb );
274                   glVertex3fv ( pv[         m * ( nc + 1 ) ].xyz );
275                   glVertex3fv ( pv[ ( m + 1 ) * ( nc + 1 ) ].xyz );
276                   for ( i = 1; i < nc + 1; ++i )
277                   {
278                     glColor3fv  ( pfc[            i - 1 + m * nc ].rgb );
279                     glVertex3fv ( pv[ i + ( m + 1 ) * ( nc + 1 ) ].xyz );
280                     glVertex3fv ( pv[         i + m * ( nc + 1 ) ].xyz );
281                   }
282                   glEnd ();
283                 }
284               }
285             }
286             else
287             {
288               for ( m = 0; m < nr; ++m )
289               {
290                 if ( myDS->bDraw[ m ] )
291                 {
292                   glBegin ( GL_QUADS );
293                   glVertex3fv ( pv[         m * ( nc + 1 ) ].xyz );
294                   glVertex3fv ( pv[ ( m + 1 ) * ( nc + 1 ) ].xyz );
295                   for ( i = 1; i < nc + 1; ++i )
296                   {
297                     glVertex3fv( pv[ i + ( m + 1 ) * ( nc + 1 ) ].xyz );
298                     glVertex3fv( pv[         i + m * ( nc + 1 ) ].xyz );
299                   }
300                   glEnd ();
301                 }
302               }
303             }
304           }
305         }
306         else
307         {
308           if ( !myDS->dlist ) myDS->dlist = glGenLists ( 1 );
309
310           glNewList ( myDS->dlist, GL_COMPILE_AND_EXECUTE );
311           newList = 1;
312
313         }  /* end else */
314         if ( newList ) glEndList ();
315
316         if ( AWorkspace->DegenerateModel ) return;
317
318       } else {
319
320         glCallList ( AWorkspace->SkipRatio <= 0.f ? myDS->list : myDS->dlist );
321
322         if ( AWorkspace->DegenerateModel ) return;
323
324       }  /* end else */
325   }
326
327   i = 0;
328
329   /* OCC11904 -- Temporarily disable environment mapping */
330   glPushAttrib(GL_ENABLE_BIT);
331   glDisable(GL_TEXTURE_1D);
332   glDisable(GL_TEXTURE_2D);
333
334   switch ( AWorkspace->DegenerateModel )
335   {
336     default:
337       break;
338
339     case 2:  /* XXX_TDM_WIREFRAME */
340       i = 1;
341       break;
342
343     case 3:  /* XXX_TDM_MARKER */
344       draw_degenerates_as_points ( myDS, myData.vertices, ( myData.num_rows + 1 ) * ( myData.num_columns + 1 ), AWorkspace );
345       glPopAttrib();
346       return;
347
348     case 4:  /* XXX_TDM_BBOX */
349       draw_degenerates_as_bboxs ( myDS, myData.vertices, ( myData.num_rows + 1 ) * ( myData.num_columns + 1 ), AWorkspace );
350       glPopAttrib();
351       return;
352   }  /* end switch */
353
354   draw_edges ( edge_colour, interior_style, i, AWorkspace );
355
356   glPopAttrib();
357 }
358
359 /*----------------------------------------------------------------------*/
360
361 void OpenGl_QuadrangleStrip::draw_edges (const TEL_COLOUR *edge_colour, const Aspect_InteriorStyle interior_style,
362                                         Tint forceDraw, const Handle(OpenGl_Workspace) &AWorkspace) const
363 {
364   const OpenGl_AspectFace *aspect_face = AWorkspace->AspectFace( Standard_True );
365
366   if ( interior_style != Aspect_IS_HIDDENLINE && !forceDraw && aspect_face->Context().Edge == TOff )
367     return;
368
369   glDisable(GL_LIGHTING);
370   const GLboolean texture_on = IsTextureEnabled();
371   if ( texture_on ) DisableTexture();
372
373   // Setup line aspect
374   const OpenGl_AspectLine *aspect_line_old = AWorkspace->SetAspectLine( aspect_face->AspectEdge() );
375   AWorkspace->AspectLine( Standard_True );
376
377   tel_point pv = myData.vertices;
378   Tint nc = myData.num_columns;
379   Tint nf = myData.num_rows * myData.num_columns;
380
381   Tint newList = 0;
382
383   if ( !forceDraw )
384     draw_line_strip ( edge_colour, nf, nc );
385   else
386   {
387     if ( (AWorkspace->NamedStatus & OPENGL_NS_ANIMATION) == 0 )
388       goto doDraw; /* Disable object display list out of animation */
389     if ( myDS->degMode != 2 || myDS->skipRatio != AWorkspace->SkipRatio || !myDS->dlist ) {
390
391       if ( !myDS->dlist ) myDS->dlist = glGenLists ( 1 );
392
393       myDS->degMode   = 2;
394       myDS->skipRatio = AWorkspace->SkipRatio;
395       glNewList ( myDS->dlist, GL_COMPILE_AND_EXECUTE );
396       newList = 1;
397 doDraw:
398       glPushAttrib ( GL_DEPTH_BUFFER_BIT );
399       glDisable ( GL_DEPTH_TEST );
400
401       if ( AWorkspace->SkipRatio <= 0.f )
402
403         draw_line_strip ( edge_colour, nf, nc );
404
405       else if ( AWorkspace->SkipRatio < 1.f ) {
406
407         int i, m1, m2, n1, n2, n3, n4;
408
409         set_drawable_items ( myDS->bDraw, nf, AWorkspace->SkipRatio );
410
411         glColor3fv ( edge_colour -> rgb );
412
413         for ( i = 0; i < nf; ++i )
414
415           if ( myDS->bDraw[ i ] ) {
416
417             glBegin ( GL_LINE_STRIP );
418             m1 = i / nc;
419             m2 = i % nc;
420             n1 = m1 * ( nc + 1 ) + m2;
421             n2 = n1 + nc + 1;
422             n3 = n2 + 1;
423             n4 = n1 + 1;
424
425             glVertex3fv ( myData.vertices[ n1 ].xyz );
426             glVertex3fv ( myData.vertices[ n2 ].xyz );
427             glVertex3fv ( myData.vertices[ n3 ].xyz );
428             glVertex3fv ( myData.vertices[ n4 ].xyz );
429             glVertex3fv ( myData.vertices[ n1 ].xyz );
430             glEnd();
431
432           }  /* end if */
433
434       }  /* end if */
435
436       glPopAttrib ();
437       if ( newList ) glEndList ();
438
439     } else glCallList ( myDS->dlist );
440
441   }  /* end else */
442
443   // Restore line context
444   AWorkspace->SetAspectLine( aspect_line_old );
445
446   if ( texture_on ) EnableTexture ();
447 }
448
449 void OpenGl_QuadrangleStrip::draw_line_strip (const TEL_COLOUR *c, Tint nf, Tint nc) const
450 {
451   int i, m1, m2, n1, n2, n3, n4;
452
453   glColor3fv ( c->rgb );
454
455   for ( i = 0; i < nf; ++i )
456   {
457     glBegin ( GL_LINE_STRIP );
458     m1 = i / nc;
459     m2 = i % nc;
460     n1 = m1 * ( nc + 1 ) + m2;
461     n2 = n1 + nc + 1;
462     n3 = n2 + 1;
463     n4 = n1 + 1;
464
465     glVertex3fv ( myData.vertices[ n1 ].xyz );
466     glVertex3fv ( myData.vertices[ n2 ].xyz );
467     glVertex3fv ( myData.vertices[ n3 ].xyz );
468     glVertex3fv ( myData.vertices[ n4 ].xyz );
469     glVertex3fv ( myData.vertices[ n1 ].xyz );
470     glEnd();
471   }
472 }
473
474 /*----------------------------------------------------------------------*/
475
476 OpenGl_QuadrangleStrip::OpenGl_QuadrangleStrip (const Graphic3d_Array2OfVertex& AListVertex)
477 {
478   const Standard_Integer nbr = AListVertex.RowLength ();
479   const Standard_Integer nbc = AListVertex.ColLength ();
480   const Standard_Integer nbf = nbr*nbc;
481
482   // Dynamic allocation
483   TEL_POINT *points = new TEL_POINT[nbf];
484
485   const Standard_Integer LowerRow = AListVertex.LowerRow ();
486   const Standard_Integer UpperRow = AListVertex.UpperRow ();
487   const Standard_Integer LowerCol = AListVertex.LowerCol ();
488   const Standard_Integer UpperCol = AListVertex.UpperCol ();
489
490   Standard_Integer i, j, k = 0;
491   Standard_Real X, Y, Z;
492   for (i=LowerRow; i<=UpperRow; i++)
493     for (j=LowerCol; j<=UpperCol; j++)
494     {
495       AListVertex (i, j).Coord (X, Y, Z);
496       points[k].xyz[0] = float (X);
497       points[k].xyz[1] = float (Y);
498       points[k].xyz[2] = float (Z);
499       k++;
500     }
501
502   Init(nbr,nbc,points,NULL,NULL,NULL,NULL,NULL,TEL_SHAPE_UNKNOWN);
503 }
504
505 /*----------------------------------------------------------------------*/
506
507 OpenGl_QuadrangleStrip::OpenGl_QuadrangleStrip (const Graphic3d_Array2OfVertexN& AListVertex)
508 {
509   const Standard_Integer nbr = AListVertex.RowLength ();
510   const Standard_Integer nbc = AListVertex.ColLength ();
511   const Standard_Integer nbf = nbr*nbc;
512
513   // Dynamic allocation
514   TEL_POINT *points = new TEL_POINT[nbf];
515   TEL_POINT *normals = new TEL_POINT[nbf];
516
517   const Standard_Integer LowerRow = AListVertex.LowerRow ();
518   const Standard_Integer UpperRow = AListVertex.UpperRow ();
519   const Standard_Integer LowerCol = AListVertex.LowerCol ();
520   const Standard_Integer UpperCol = AListVertex.UpperCol ();
521
522   Standard_Integer i, j, k = 0;
523   Standard_Real X, Y, Z;
524   for (i=LowerRow; i<=UpperRow; i++)
525     for (j=LowerCol; j<=UpperCol; j++)
526     {
527       AListVertex (i, j).Coord (X, Y, Z);
528       points[k].xyz[0] = float (X);
529       points[k].xyz[1] = float (Y);
530       points[k].xyz[2] = float (Z);
531       AListVertex (i, j).Normal (X, Y, Z);
532       normals[k].xyz[0] = float (X);
533       normals[k].xyz[1] = float (Y);
534       normals[k].xyz[2] = float (Z);
535       k++;
536     }
537
538   Init(nbr,nbc,points,normals,NULL,NULL,NULL,NULL,TEL_SHAPE_UNKNOWN);
539 }
540
541 /*----------------------------------------------------------------------*/
542
543 OpenGl_QuadrangleStrip::OpenGl_QuadrangleStrip (const Graphic3d_Array2OfVertexNT& AListVertex)
544 {
545   const Standard_Integer nbr = AListVertex.RowLength ();
546   const Standard_Integer nbc = AListVertex.ColLength ();
547   const Standard_Integer nbf = nbr*nbc;
548
549   // Dynamic allocation
550   TEL_POINT *points = new TEL_POINT[nbf];
551   TEL_POINT *normals = new TEL_POINT[nbf];
552   TEL_TEXTURE_COORD *tcoords = new TEL_TEXTURE_COORD[nbf];
553
554   const Standard_Integer LowerRow = AListVertex.LowerRow ();
555   const Standard_Integer UpperRow = AListVertex.UpperRow ();
556   const Standard_Integer LowerCol = AListVertex.LowerCol ();
557   const Standard_Integer UpperCol = AListVertex.UpperCol ();
558
559   Standard_Integer i, j, k = 0;
560   Standard_Real X, Y, Z;
561   for (i=LowerRow; i<=UpperRow; i++)
562     for (j=LowerCol; j<=UpperCol; j++)
563     {
564       AListVertex (i, j).Coord (X, Y, Z);
565       points[k].xyz[0] = float (X);
566       points[k].xyz[1] = float (Y);
567       points[k].xyz[2] = float (Z);
568       AListVertex (i, j).Normal (X, Y, Z);
569       normals[k].xyz[0] = float (X);
570       normals[k].xyz[1] = float (Y);
571       normals[k].xyz[2] = float (Z);
572       AListVertex (i, j).TextureCoordinate(X, Y);
573       tcoords[k].xy[0] = float(X);
574       tcoords[k].xy[1] = float(Y);
575       k++;
576     }
577
578   Init(nbr,nbc,points,normals,NULL,tcoords,NULL,NULL,TEL_SHAPE_UNKNOWN);
579 }
580
581 /*----------------------------------------------------------------------*/
582
583 void OpenGl_QuadrangleStrip::Init (const Tint ANbRows, const Tint ANbCols, tel_point AVertices,
584                                   tel_point AVNormals, tel_colour AVColors, tel_texture_coord ATCoords,
585                                   tel_point AFNormals, tel_colour AFColors, const Tint AShapeFlag)
586 {
587   myData.num_rows    = ANbRows;
588   myData.num_columns = ANbCols;
589
590   const Tint nf = ANbRows * ANbCols;
591   const Tint nv = ( ANbRows+1 ) * ( ANbCols+1 );
592
593   Tint i;
594
595   // Store vertices
596   myData.vertices = AVertices;
597
598   // Store or compute (based on vertices) facet normals
599   if (AFNormals)
600   {
601     myData.facet_flag = TEL_FA_NORMAL;
602     myData.fnormals = new TEL_POINT[nf];
603     memcpy( myData.fnormals, AFNormals, nf*sizeof(TEL_POINT) );
604     for( i = 0; i < nf; i++ )
605       vecnrm( myData.fnormals[i].xyz );
606   }
607   else
608   {
609     myData.facet_flag = TEL_FA_NONE;
610     myData.fnormals = new TEL_POINT[nf];
611     for( i = 0; i < nf; i++ )
612     {
613       const Tint r = i/ANbCols;
614       const Tint c = i%ANbCols;
615       const Tint id = r*(ANbCols+1) + c;
616
617       TEL_POINT  p1, p2, p3, p4;
618
619       p1 = myData.vertices[id];
620       p2 = myData.vertices[id+ANbCols+1];
621       p3 = myData.vertices[id+ANbCols+2];
622       p4 = myData.vertices[id+1];
623
624       p4.xyz[0] -= p2.xyz[0];
625       p4.xyz[1] -= p2.xyz[1];
626       p4.xyz[2] -= p2.xyz[2];
627
628       p4.xyz[0] += p1.xyz[0];
629       p4.xyz[1] += p1.xyz[1];
630       p4.xyz[2] += p1.xyz[2];
631
632       TelGetNormal( p4.xyz, p1.xyz, p3.xyz, myData.fnormals[i].xyz );
633     }
634   }
635
636   // Store or compute (based on facet normals) vertex normals
637   if (AVNormals)
638   {
639     myData.vertex_flag = TEL_VT_NORMAL;
640     myData.vnormals = AVNormals;
641     for( i = 0; i < nv; i++ )
642       vecnrm( myData.vnormals[i].xyz );
643   }
644   else
645   {
646     myData.vertex_flag = TEL_VT_NONE;
647     myData.vnormals = new TEL_POINT[nv];
648     Tint r, c, id;
649     for( i = 0; i < nv; i++ )
650     {
651       if( i == 0 )
652         myData.vnormals[i] = myData.fnormals[i];
653       else if( i == (nv-1) )
654         myData.vnormals[i] = myData.fnormals[nf-1];
655       else if( i == (nv-ANbCols-1) )
656         myData.vnormals[i] = myData.fnormals[nf-ANbCols];
657       else if( i == ANbCols )
658         myData.vnormals[i] = myData.fnormals[i-1];
659       else if( i%(ANbCols+1) == 0 )
660       {
661         r = i/(myData.num_columns+1);
662         myData.vnormals[i].xyz[0] = ( myData.fnormals[(r-1)*ANbCols].xyz[0] + myData.fnormals[r*ANbCols].xyz[0] ) / 2.0F;
663         myData.vnormals[i].xyz[1] = ( myData.fnormals[(r-1)*ANbCols].xyz[1] + myData.fnormals[r*ANbCols].xyz[1] ) / 2.0F;
664         myData.vnormals[i].xyz[2] = ( myData.fnormals[(r-1)*ANbCols].xyz[2] + myData.fnormals[r*ANbCols].xyz[2] ) / 2.0F;
665       }
666       else if( i <= ANbCols )
667       {
668         myData.vnormals[i].xyz[0] = ( myData.fnormals[i-1].xyz[0] + myData.fnormals[i].xyz[0] ) / 2.0F;
669         myData.vnormals[i].xyz[1] = ( myData.fnormals[i-1].xyz[1] + myData.fnormals[i].xyz[1] ) / 2.0F;
670         myData.vnormals[i].xyz[2] = ( myData.fnormals[i-1].xyz[2] + myData.fnormals[i].xyz[2] ) / 2.0F;
671       }
672       else if( i >= (nv-ANbCols-1 ) )
673       {
674         c = i%(ANbCols+1);
675         id = nf-ANbCols+c;
676
677         myData.vnormals[i].xyz[0] = ( myData.fnormals[id-1].xyz[0] + myData.fnormals[id].xyz[0] ) / 2.0F;
678         myData.vnormals[i].xyz[1] = ( myData.fnormals[id-1].xyz[1] + myData.fnormals[id].xyz[1] ) / 2.0F;
679         myData.vnormals[i].xyz[2] = ( myData.fnormals[id-1].xyz[2] + myData.fnormals[id].xyz[2] ) / 2.0F;
680       }
681       else if( (i+1)%(ANbCols+1) == 0 )
682       {
683         r = (i+1)/(ANbCols+1);
684         myData.vnormals[i].xyz[0] = ( myData.fnormals[(r-1)*ANbCols-1].xyz[0] + myData.fnormals[r*ANbCols-1].xyz[0] ) / 2.0F;
685         myData.vnormals[i].xyz[1] = ( myData.fnormals[(r-1)*ANbCols-1].xyz[1] + myData.fnormals[r*ANbCols-1].xyz[1] ) / 2.0F;
686         myData.vnormals[i].xyz[2] = ( myData.fnormals[(r-1)*ANbCols-1].xyz[2] + myData.fnormals[r*ANbCols-1].xyz[2] ) / 2.0F;
687       }
688       else
689       {
690         r = i/(ANbCols+1);
691         c = i%(ANbCols+1);
692
693         id = r*ANbCols+c;
694
695         myData.vnormals[i].xyz[0] = ( myData.fnormals[id].xyz[0] + myData.fnormals[id-ANbCols].xyz[0] + myData.fnormals[id-1].xyz[0] + myData.fnormals[id-ANbCols-1].xyz[0] ) / 4.0F;
696         myData.vnormals[i].xyz[1] = ( myData.fnormals[id].xyz[1] + myData.fnormals[id-ANbCols].xyz[1] + myData.fnormals[id-1].xyz[1] + myData.fnormals[id-ANbCols-1].xyz[1] ) / 4.0F;
697         myData.vnormals[i].xyz[2] = ( myData.fnormals[id].xyz[2] + myData.fnormals[id-ANbCols].xyz[2] + myData.fnormals[id-1].xyz[2] + myData.fnormals[id-ANbCols-1].xyz[2] ) / 4.0F;
698       }
699     }
700   }
701
702   myData.vcolours = AVColors;
703   myData.vtexturecoord = ATCoords;
704   myData.fcolours = AFColors;
705
706   myData.shape_flag = AShapeFlag;
707
708   myDS = new DS_INTERNAL;
709   myDS->list      =  0;
710   myDS->dlist     =  0;
711   myDS->degMode   =  0;
712   myDS->model     = -1;
713   myDS->skipRatio =  0.0F;
714   myDS->bDraw = new unsigned char[nv];
715 }
716
717 /*----------------------------------------------------------------------*/
718
719 OpenGl_QuadrangleStrip::~OpenGl_QuadrangleStrip ()
720 {
721   if( myData.fnormals )
722     delete[] myData.fnormals;
723   if( myData.fcolours )
724     delete[] myData.fcolours;
725   if( myData.vertices )
726     delete[] myData.vertices;
727   if( myData.vcolours )
728     delete[] myData.vcolours;
729   if( myData.vnormals )
730     delete[] myData.vnormals;
731   if ( myData.vtexturecoord )
732     delete[] myData.vtexturecoord;
733
734   if ( myDS )
735   {
736     if (  GET_GL_CONTEXT() != NULL  )
737     {
738       if ( myDS->list ) glDeleteLists ( myDS->list, 1 );
739       if ( myDS->dlist ) glDeleteLists ( myDS->dlist, 1 );
740     }
741     if ( myDS->bDraw )
742       delete[] myDS->bDraw;
743
744         delete myDS;
745   }
746 }
747
748 /*----------------------------------------------------------------------*/
749
750 void OpenGl_QuadrangleStrip::Render (const Handle(OpenGl_Workspace) &AWorkspace) const
751 {
752   const OpenGl_AspectFace *aspect_face = AWorkspace->AspectFace( Standard_True );
753
754   Tint front_lighting_model = aspect_face->Context().IntFront.color_mask;
755   const TEL_COLOUR *interior_colour = &aspect_face->Context().IntFront.matcol;
756   const TEL_COLOUR *edge_colour = &aspect_face->AspectEdge()->Color();
757
758   // Use highlight colors
759   if ( AWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT )
760   {                         
761     edge_colour = interior_colour = AWorkspace->HighlightColor;
762     front_lighting_model = 0;
763   }
764
765   glColor3fv( interior_colour->rgb );
766
767   draw_qstrip( front_lighting_model,
768                aspect_face->Context().InteriorStyle,
769                edge_colour,
770                AWorkspace );
771 }
772
773 /*----------------------------------------------------------------------*/